Skip to content

Commit b7ada6c

Browse files
authored
Merge pull request #606 from jembi/PLAT-707-kafka-integration
PLAT-707 Add kafka integration
2 parents 0161ba7 + ed8b082 commit b7ada6c

File tree

7 files changed

+162
-66
lines changed

7 files changed

+162
-66
lines changed

app/config/default.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"version": "1.17.0",
2+
"version": "1.18.0",
33
"minimumCoreVersion": "5.0.0",
44
"protocol": "https",
55
"host": "localhost",

app/scripts/controllers/channel-tabs/routes.js

Lines changed: 73 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,11 @@ export function channelRoutesCtrl ($scope, $timeout, Api, Alerting) {
114114
password: '',
115115
type: 'http',
116116
status: 'enabled',
117-
forwardAuthHeader: false
117+
forwardAuthHeader: false,
118+
kafkaClientId: '',
119+
kafkaTopic: '',
120+
waitPrimaryResponse: false,
121+
statusCodesCheck: '',
118122
}
119123
} else if (type === 'edit') {
120124
// show add/edit box
@@ -220,26 +224,47 @@ export function channelRoutesCtrl ($scope, $timeout, Api, Alerting) {
220224
$scope.ngErrorRoute.hasErrors = true
221225
}
222226

223-
// host validation
224-
if (!$scope.newRoute.host) {
225-
$scope.ngErrorRoute.host = true
227+
// Status codes validation
228+
const codeError = $scope.checkIsStatusCodesValid($scope.newRoute.statusCodesCheck)
229+
if (codeError) {
230+
$scope.ngErrorRoute.statusCodesCheck = true
231+
$scope.ngErrorRoute.statusCodesCheckError = codeError
226232
$scope.ngErrorRoute.hasErrors = true
227233
}
228234

229-
// port validation
230-
const portError = $scope.checkIsPortValid($scope.newRoute.port)
231-
if (portError) {
232-
$scope.ngErrorRoute.port = true
233-
$scope.ngErrorRoute.portError = portError
234-
$scope.ngErrorRoute.hasErrors = true
235-
}
235+
// HTTP route type validation
236+
if ($scope.newRoute.type === 'http') {
237+
// host validation
238+
if (!$scope.newRoute.host) {
239+
$scope.ngErrorRoute.host = true
240+
$scope.ngErrorRoute.hasErrors = true
241+
}
236242

237-
// path/transform validation
238-
const pathTransformError = $scope.checkPathTransformPathSet($scope.newRoute)
239-
if (pathTransformError) {
240-
$scope.ngErrorRoute.pathTransform = true
241-
$scope.ngErrorRoute.pathTransformError = pathTransformError
242-
$scope.ngErrorRoute.hasErrors = true
243+
// port validation
244+
const portError = $scope.checkIsPortValid($scope.newRoute.port)
245+
if (portError) {
246+
$scope.ngErrorRoute.port = true
247+
$scope.ngErrorRoute.portError = portError
248+
$scope.ngErrorRoute.hasErrors = true
249+
}
250+
251+
// path/transform validation
252+
const pathTransformError = $scope.checkPathTransformPathSet($scope.newRoute)
253+
if (pathTransformError) {
254+
$scope.ngErrorRoute.pathTransform = true
255+
$scope.ngErrorRoute.pathTransformError = pathTransformError
256+
$scope.ngErrorRoute.hasErrors = true
257+
}
258+
}
259+
// KAFKA route type validation
260+
if ($scope.newRoute.type === 'kafka') {
261+
// kafka topic validation
262+
const kafkaTopicError = $scope.checkIskafkaTopicValid($scope.newRoute.kafkaTopic)
263+
if (kafkaTopicError) {
264+
$scope.ngErrorRoute.kafkaTopic = true
265+
$scope.ngErrorRoute.kafkaTopicError = kafkaTopicError
266+
$scope.ngErrorRoute.hasErrors = true
267+
}
243268
}
244269

245270
if ($scope.ngErrorRoute.hasErrors) {
@@ -277,6 +302,37 @@ export function channelRoutesCtrl ($scope, $timeout, Api, Alerting) {
277302
}
278303
}
279304

305+
// check if topic name is valid by kafka
306+
$scope.checkIskafkaTopicValid = function (value) {
307+
if (value) {
308+
if(value.length > 255) {
309+
return 'Max length is 255 characters!'
310+
}
311+
for(let char of value) {
312+
if(!/[a-zA-Z0-9\\._\\-]/.test(char)) {
313+
return 'Not valid topic name! Only letters, numbers, . (dot), _ (underscore), - (minus) can be used!'
314+
}
315+
}
316+
} else {
317+
return 'This field is required!'
318+
}
319+
}
320+
321+
// validate status codes provided
322+
$scope.checkIsStatusCodesValid = function (value) {
323+
if (value !== '' && value !== undefined) {
324+
const codes = value.split(',')
325+
for (const code of codes) {
326+
const validRangeCodes = ["1**", "2**", "3**", "4**", "5**"];
327+
if (Number(code) <= 100 || Number(code) >= 599) {
328+
return `${code} not a valid status code!`
329+
} else if (code.includes('*') && !validRangeCodes.includes(code)) {
330+
return `${code} not a valid range of codes! valid options: ${validRangeCodes}`
331+
}
332+
}
333+
}
334+
}
335+
280336
$scope.noRoutes = function () {
281337
// no routes found - return true
282338
if (!$scope.channel.routes || $scope.channel.routes.length === 0) {

app/views/partials/channels-tab-routes.html

Lines changed: 83 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,10 @@ <h3>Set Route</h3>
3737
<label>Route Type</label><br />
3838
<div class="btn-group" style="clear: both;">
3939
<label class="btn btn-primary" ng-model="newRoute.type" uib-btn-radio="'http'">HTTP</label>
40-
<label class="btn btn-primary" ng-model="newRoute.type" uib-btn-radio="'tcp'">TCP</label>
41-
<label class="btn btn-primary" ng-model="newRoute.type" uib-btn-radio="'mllp'">MLLP</label>
40+
<label class="btn btn-primary" ng-model="newRoute.type" uib-btn-radio="'kafka'">KAFKA</label>
4241
</div>
4342
</div>
44-
<div class="form-group" style="float: left; margin-left: 20px;">
43+
<div class="form-group" style="float: left; margin-left: 20px;" ng-if="newRoute.type=='http'">
4544
<label>Route Secured</label><br />
4645
<div class="btn-group" style="clear: both;">
4746
<label class="btn btn-primary" ng-model="newRoute.secured" uib-btn-radio="true">Yes</label>
@@ -55,47 +54,78 @@ <h3>Set Route</h3>
5554
</select>
5655
</div>
5756
</div>
58-
<div class="form-group-2columns">
59-
<div class="form-group" style="float: left;" ng-class="{ 'has-error' : ngErrorRoute.host }">
60-
<label><span style="color: #a94442;">*</span> Host</label>
61-
<input ng-model="newRoute.host" class="form-control" placeholder="Route Host" type="text" />
62-
<div class="has-error-msg"><i class="glyphicon glyphicon-warning-sign"></i>{{validationRequiredMsg}}</div>
63-
</div>
64-
<div class="form-group" style="float: left; margin-left: 20px;" ng-class="{ 'has-error' : ngErrorRoute.port }">
65-
<label><span style="color: #a94442;">*</span> Port</label><br />
66-
<input ng-model="newRoute.port" class="form-control" placeholder="Route Port" type="text" />
67-
<div class="has-error-msg"><i class="glyphicon glyphicon-warning-sign"></i>{{ngErrorRoute.portError}}</div>
68-
</div>
69-
</div>
70-
<div class="form-group-2columns" ng-class="{ 'has-error' : ngErrorRoute.pathTransform }">
57+
<div ng-show="newRoute.primary==false" class="form-group-2columns" style="display: inline-block; width: 100%">
7158
<div class="form-group" style="float: left;">
72-
<label><span style="color: #a94442;">**</span> Route Path</label>
73-
<input ng-model="newRoute.path" class="form-control" placeholder="Route Path" type="text" />
59+
<label>Wait for the response of the primary route</label><br />
60+
<div class="btn-group" style="clear: both;">
61+
<label class="btn btn-primary" ng-model="newRoute.waitPrimaryResponse" uib-btn-radio="true">Yes</label>
62+
<label class="btn btn-primary" ng-model="newRoute.waitPrimaryResponse" uib-btn-radio="false">No</label>
63+
</div>
7464
</div>
75-
<div class="form-group" style="float: left; margin-left: 20px;">
65+
<div class="form-group" style="float: left; margin-left: 20px;" ng-show="newRoute.waitPrimaryResponse==true" ng-class="{ 'has-error' : ngErrorRoute.statusCodesCheck }">
7666
<label>
77-
<span style="color: #a94442;">**</span> Route Path Transform
78-
<i ng-show="uiSettings.showTooltips" uib-tooltip-html="'Transform the route path by using the following substitute expression format:<br /> s/from/to/g'" class="glyphicon glyphicon-question-sign tooltip-wide"></i>
67+
Send request when matching status code
68+
<i ng-show="uiSettings.showTooltips" uib-tooltip="Request will NOT be sent to the secondary route(s) unless the response status of the primary route match one of these status codes. A single value or a list are both accepted. A list should be comma separated (single status codes e.g. 200,201, range e.g. 2**,3**, mixture of both e.g. 204,3**)." class="glyphicon glyphicon-question-sign tooltip-wide" style="font-size: 12px"></i>
7969
</label><br />
80-
<input ng-model="newRoute.pathTransform" class="form-control" placeholder="s/from/to/g " type="text" />
70+
<input class="form-control" placeholder="e.g. 2**,404,500" type="text" ng-model="newRoute.statusCodesCheck" />
71+
<div class="has-error-msg"><i class="glyphicon glyphicon-warning-sign"></i>{{ngErrorRoute.statusCodesCheckError}}</div>
8172
</div>
82-
<div class="has-error-msg" style="clear: both; margin-bottom: 5px;"><i class="glyphicon glyphicon-warning-sign"></i>{{ngErrorRoute.pathTransformError}}</div>
8373
</div>
84-
<div class="form-group-2columns">
85-
<div class="form-group" style="float: left;">
86-
<label>Basic Authentication Username</label>
87-
<input ng-model="newRoute.username" ng-disabled="newRoute.forwardAuthHeader" class="form-control" placeholder="Basic Authentication Username" type="text" />
74+
<div ng-show="newRoute.type=='http'">
75+
<div class="form-group-2columns">
76+
<div class="form-group" style="float: left;" ng-class="{ 'has-error' : ngErrorRoute.host }">
77+
<label><span style="color: #a94442;">*</span> Host</label>
78+
<input ng-model="newRoute.host" class="form-control" placeholder="Route Host" type="text" />
79+
<div class="has-error-msg"><i class="glyphicon glyphicon-warning-sign"></i>{{validationRequiredMsg}}</div>
80+
</div>
81+
<div class="form-group" style="float: left; margin-left: 20px;" ng-class="{ 'has-error' : ngErrorRoute.port }">
82+
<label><span style="color: #a94442;">*</span> Port</label><br />
83+
<input ng-model="newRoute.port" class="form-control" placeholder="Route Port" type="text" />
84+
<div class="has-error-msg"><i class="glyphicon glyphicon-warning-sign"></i>{{ngErrorRoute.portError}}</div>
85+
</div>
8886
</div>
89-
<div class="form-group" style="float: left; margin-left: 20px;">
90-
<label>Basic Authentication Password</label><br />
91-
<input ng-model="newRoute.password" ng-disabled="newRoute.forwardAuthHeader" class="form-control" placeholder="Basic Authentication Password" type="text" />
87+
<div class="form-group-2columns" ng-class="{ 'has-error' : ngErrorRoute.pathTransform }">
88+
<div class="form-group" style="float: left;">
89+
<label><span style="color: #a94442;">**</span> Route Path</label>
90+
<input ng-model="newRoute.path" class="form-control" placeholder="Route Path" type="text" />
91+
</div>
92+
<div class="form-group" style="float: left; margin-left: 20px;">
93+
<label>
94+
<span style="color: #a94442;">**</span> Route Path Transform
95+
<i ng-show="uiSettings.showTooltips" uib-tooltip-html="'Transform the route path by using the following substitute expression format:<br /> s/from/to/g'" class="glyphicon glyphicon-question-sign tooltip-wide"></i>
96+
</label><br />
97+
<input ng-model="newRoute.pathTransform" class="form-control" placeholder="s/from/to/g " type="text" />
98+
</div>
99+
<div class="has-error-msg" style="clear: both; margin-bottom: 5px;"><i class="glyphicon glyphicon-warning-sign"></i>{{ngErrorRoute.pathTransformError}}</div>
92100
</div>
93-
<div class="form-group" style="float: left;">
94-
<label>Forward existing Authorization header</label><br />
95-
<div class="btn-group" style="clear: both;">
96-
<label class="btn btn-primary" ng-model="newRoute.forwardAuthHeader" uib-btn-radio="true">Yes</label>
97-
<label class="btn btn-primary" ng-model="newRoute.forwardAuthHeader" uib-btn-radio="false">No</label>
101+
<div class="form-group-2columns">
102+
<div class="form-group" style="float: left;">
103+
<label>Basic Authentication Username</label>
104+
<input ng-model="newRoute.username" ng-disabled="newRoute.forwardAuthHeader" class="form-control" placeholder="Basic Authentication Username" type="text" />
105+
</div>
106+
<div class="form-group" style="float: left; margin-left: 20px;">
107+
<label>Basic Authentication Password</label><br />
108+
<input ng-model="newRoute.password" ng-disabled="newRoute.forwardAuthHeader" class="form-control" placeholder="Basic Authentication Password" type="text" />
98109
</div>
110+
<div class="form-group" style="float: left;">
111+
<label>Forward existing Authorization header</label><br />
112+
<div class="btn-group" style="clear: both;">
113+
<label class="btn btn-primary" ng-model="newRoute.forwardAuthHeader" uib-btn-radio="true">Yes</label>
114+
<label class="btn btn-primary" ng-model="newRoute.forwardAuthHeader" uib-btn-radio="false">No</label>
115+
</div>
116+
</div>
117+
</div>
118+
</div>
119+
<div ng-show="newRoute.type=='kafka'">
120+
<div class="form-group" ng-class="{ 'has-error' : ngErrorRoute.kafkaClientId }">
121+
<label><span>*</span> Client ID</label>
122+
<input class="form-control" placeholder="e.g. openhim-route" type="text" ng-model="newRoute.kafkaClientId" />
123+
<div class="has-error-msg"><i class="glyphicon glyphicon-warning-sign"></i>{{validationRequiredMsg}}</div>
124+
</div>
125+
<div class="form-group" ng-class="{ 'has-error' : ngErrorRoute.kafkaTopic }">
126+
<label><span>*</span> Topic Name</label>
127+
<input class="form-control" placeholder="e.g. 2xx-topic" type="text" ng-model="newRoute.kafkaTopic" />
128+
<div class="has-error-msg"><i class="glyphicon glyphicon-warning-sign"></i>{{ngErrorRoute.kafkaTopicError}}</div>
99129
</div>
100130
</div>
101131

@@ -118,8 +148,8 @@ <h3>Set Route</h3>
118148
<tr style="font-weight: bold">
119149
<th>
120150
<div style="width: 23%; float: left; display: block; margin-right: 1%;">Name | Status | Primary</div>
121-
<div style="width: 18%; float: left; display: block; margin-right: 1%;">Type | Secured</div>
122-
<div style="width: 23%; float: left; display: block; margin-right: 1%;">Host | Port</div>
151+
<div style="width: 18%; float: left; display: block; margin-right: 1%;">Type | Secured | Conditional</div>
152+
<div style="width: 23%; float: left; display: block; margin-right: 1%;">Host | Port | Topic</div>
123153
<div style="width: 23%; float: left; display: block; margin-right: 1%;">Path/Transform</div>
124154
<div style="width: 8%; float: right; display: block;"></div>
125155
</th>
@@ -143,19 +173,27 @@ <h3>Set Route</h3>
143173
</div>
144174
<div style="width: 18%; float: left; display: block; margin-right: 1%;">
145175
<span ng-if="route.type=='http'" class="btn-info btn-xs">HTTP</span>
146-
<span ng-if="route.type=='tcp'" class="btn-warning btn-xs">TCP</span>
147-
<span ng-if="route.type=='mllp'" class="btn-primary btn-xs">MLLP</span>
176+
<span ng-if="route.type=='kafka'" class="btn-warning btn-xs">KAFKA</span>
148177

149-
<span ng-if="route.secured==true" class="btn-success btn-xs">Secured</span>
150-
<span ng-if="route.secured==false" class="btn-danger btn-xs">Unsecured</span>
178+
<span ng-if="route.secured==true && route.type=='http'" class="btn-success btn-xs">Secured</span>
179+
<span ng-if="route.secured==false && route.type=='http'" class="btn-danger btn-xs">Unsecured</span>
180+
181+
<span ng-if="route.waitPrimaryResponse==true" class="btn-warning btn-xs">Conditional</span>
151182
</div>
152183
<div style="width: 23%; float: left; display: block; margin-right: 1%;">
153-
<span>{{ route.host }}</span>
154-
<span>{{ route.port }}</span>
184+
<span ng-show="route.type=='http'">
185+
<span>{{ route.host }}</span>
186+
<span>{{ route.port }}</span>
187+
</span>
188+
<span ng-show="route.type=='kafka'">
189+
<span>{{ route.kafkaTopic }}</span>
190+
</span>
155191
</div>
156192
<div style="width: 23%; float: left; display: block; margin-right: 1%;">
157-
<span>{{ route.path }}</span>
158-
<span>{{ route.pathTransform }}</span>
193+
<span ng-show="route.type=='http'">
194+
<span>{{ route.path }}</span>
195+
<span>{{ route.pathTransform }}</span>
196+
</span>
159197
</div>
160198

161199

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "openhim-console",
33
"description": "This application provides a web application to configure and manage the OpenHIM-core component.",
4-
"version": "1.17.0",
4+
"version": "1.18.0",
55
"dependencies": {
66
"@types/http-server": "^0.10.1",
77
"http-server": "^0.12.3",

packaging/build-docker-centos-rpm.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
RELEASE_VERSION=$1
44
if [ -z ${RELEASE_VERSION} ]
55
then
6-
echo "You need so specify the release version you wish to build: e.g './build-docker-centos-rpm.sh 1.17.0'"
6+
echo "You need so specify the release version you wish to build: e.g './build-docker-centos-rpm.sh 1.18.0'"
77
echo "https://github.com/jembi/openhim-console/releases"
88
exit
99
fi

test/spec/controllers/channelsmodal.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,7 @@ describe('Controller: channelRoutesCtrl', function () {
645645
httpBackend.flush()
646646

647647
scope.newRoute = {}
648+
scope.newRoute.type = 'http'
648649
scope.newRoute.name = ''
649650
scope.newRoute.host = ''
650651
scope.newRoute.port = 'qwerty'
@@ -665,6 +666,7 @@ describe('Controller: channelRoutesCtrl', function () {
665666
httpBackend.flush()
666667

667668
scope.newRoute = {}
669+
scope.newRoute.type = 'http'
668670
scope.newRoute.name = ''
669671
scope.newRoute.host = ''
670672
scope.newRoute.port = 'qwerty'

0 commit comments

Comments
 (0)