4 * Copyright 2016 RIFT.IO Inc
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
20 var Promise
= require('bluebird');
21 var utils
= require('../../../framework/core/api_utils/utils.js');
22 var request
= utils
.request
;
23 var constants
= require('../../../framework/core/api_utils/constants.js');
24 var _
= require('lodash');
25 var APIVersion
= '/v2';
26 var transforms
= require('./transforms.js');
35 var SysLogViewer
= {};
41 // TODO: Consolidate the build functions, provide method type as arg
43 function buildGetRequestOptions(req
, endpoint
) {
44 var headers
= _
.extend({},
45 constants
.HTTP_HEADERS
.accept
.data
, {
46 'Authorization': req
.get('Authorization')
48 var api_server
= req
.query
["api_server"];
49 var requestOptions
= {
50 url
: utils
.confdPort(api_server
) + endpoint
,
53 forever
: constants
.FOREVER_ON
,
54 rejectUnauthorized
: false
56 return requestOptions
;
59 function buildPutRequestOptions(req
, endpoint
, jsonData
) {
60 var headers
= _
.extend({},
61 constants
.HTTP_HEADERS
.accept
.data
,
62 constants
.HTTP_HEADERS
.content_type
.data
, {
63 'Authorization': req
.get('Authorization')
65 var api_server
= req
.query
["api_server"];
66 var requestOptions
= {
67 url
: utils
.confdPort(api_server
) + endpoint
,
70 forever
: constants
.FOREVER_ON
,
71 rejectUnauthorized
: false,
74 return requestOptions
;
78 function buildDeleteRequestOptions(req
, endpoint
) {
79 var headers
= _
.extend({},
80 constants
.HTTP_HEADERS
.accept
.data
,
81 constants
.HTTP_HEADERS
.content_type
.data
, {
82 'Authorization': req
.get('Authorization')
84 var api_server
= req
.query
["api_server"];
85 var requestOptions
= {
86 url
: utils
.confdPort(api_server
) + endpoint
,
89 forever
: constants
.FOREVER_ON
,
90 rejectUnauthorized
: false
92 return requestOptions
;
96 * Used for simulating latency
98 function resolve_with_delay(resolve
, data
, delay
) {
99 return setTimeout(function() {
105 * This function provides the default callback for requests
107 function requestCallback(resolve
, reject
, transformFunc
) {
108 return function(error
, response
, body
) {
109 if (utils
.validateResponse('', error
, response
, body
, resolve
, reject
)) {
111 var data
= transformFunc(response
.body
);
113 var data
= JSON
.stringify(response
.body
);
116 statusCode
: response
.statusCode
,
123 function handleGetRequest(req
, endpoint
, responseTransform
) {
124 return new Promise(function(resolve
, reject
) {
126 buildGetRequestOptions(req
, endpoint
),
127 requestCallback(resolve
, reject
, responseTransform
)
135 // TODO: Add arg for transform function to transfrm req.body to json data
136 // Right now we'll just pass the request through, until we need to implement
138 function handlePutRequest(req
, endpoint
, body
) {
139 return new Promise(function(resolve
, reject
) {
141 buildPutRequestOptions(req
, endpoint
, body
||req
.body
),
142 requestCallback(resolve
, reject
)
147 function handleDeleteRequest(req
, endpoint
, body
) {
148 return new Promise(function(resolve
, reject
) {
150 buildDeleteRequestOptions(req
, endpoint
),
151 requestCallback(resolve
, reject
)
156 function handleMockResponse(req
, success
, statusCode
, data
, delay
) {
158 return new Promise(function(resolve
, reject
) {
160 resolve_with_delay(resolve
, { statusCode
: statusCode
, data
: data
}, delay
)
161 } else { reject({ statusCode
: statusCode
, data
: data
}); }
166 function handleReject(req
, statusCode
, message
) {
167 return new Promise(function(resolve
, reject
) {
168 reject({ statusCode
: statusCode
, data
: message
});
173 * Calllback function to parse the response body into an object and
174 * remove the restconf top level key if it is present.
176 function transformLoggingRootResponseCallback(responseBody
) {
177 var data
= JSON
.parse(responseBody
);
178 if (data
['rwlog-mgmt:logging']) {
179 data
= data
['rwlog-mgmt:logging'];
188 function dumpLoggingConfig(data
) {
189 console
.log("dumpLoggingconfig");
190 var logConfig
= data
['lwlog-mgmt:logging'] || data
;
192 console
.log("keys=", Object
.keys(logConfig
));
193 console
.log("stringify=", JSON
.stringify(logConfig
));
194 if (logConfig
['default-severity']) {
195 logConfig
['default-severity'].forEach(function(obj
) {
199 if (logConfig
['sink']) {
200 console
.log('sink=', JSON
.stringify(logConfig
['sink']));
202 if (logConfig
['console']) {
203 console
.log('console=', JSON
.stringify(logConfig
['console']));
205 if (logConfig
['deny']) {
206 console
.log('deny=', JSON
.stringify(logConfig
['deny']));
213 * This method should fill out the full data set
215 Aggregate
.get = function(req
) {
217 // get operational data
219 var configData
= Config
.get(req
);
220 var operationalData
= Operational
.get(req
);
222 return new Promise(function(resolve
, reject
) {
223 Promise
.all([configData
, operationalData
]).then(function(resolves
) {
224 //console.log("Resolved all request promises (config, operational logging data)");
225 // TODO: Make sure the statusCodes for each resulves is 200
226 var decoder
= new transforms
.LoggingConfigDecoder();
229 data
: decoder
.decode(resolves
[0], resolves
[1])
232 }).catch(function(error
) {
233 console
.log("Logging: Aggregate.get error: ", error
);
243 * This method expects the full data set (keys and values) for the logging
244 * config to replace the existing logging config
246 Aggregate
.set = function(req
) {
247 // NOTE: Left some debugging code remarked out
249 //console.log("Logging Aggregate.set called");
250 //console.log("data=", req.body);
252 // Do nothing to test delay in response
253 var encoder
= new transforms
.LoggingConfigEncoder();
254 var data
= encoder
.encode(req
.body
);
255 // console.log("Aggregate.set. encoded data=");
256 // console.log(data);
257 // dumpLoggingConfig(data);
259 'rwlog-mgmt:logging' : data
261 return handlePutRequest(req
, APIVersion
+ '/api/config/logging', setData
);
262 // if (this.mockResponse['set']) {
263 // return handleMockResponse(req, true, 201, data, delay=100);
274 * Get all currently set logging config data
276 Config
.get = function(req
) {
277 return handleGetRequest(req
, APIVersion
+ '/api/config/logging?deep',
278 transformLoggingRootResponseCallback
283 * Top level put method. Restconf cannot currently handle a global put on
284 * logging, so this method is currently for testing
286 Config
.set = function(req
) {
287 return handlePutRequest(req
, APIVersion
+ '/api/config/logging');
291 Config
.setConsole = function(req
) {
292 return handlePutRequest(req
, APIVersion
+ '/api/config/logging/console');
295 Config
.setFilter = function(req
) {
296 return handlePutRequest(req
, APIVersion
+ '/api/config/logging/console/filter');
299 Config
.setDefaultSeverity = function(req
) {
300 // TODO: verify there is one key at root of data: 'default-severity'
301 // OR just filter on the request body
302 return handlePutRequest(req
, APIVersion
+ '/api/config/logging/');
305 Config
.deleteDefaultSeverity = function(req
) {
306 // TODO: verify there is one key at root of data: 'default-severity'
307 // OR just filter on the request body
308 var Categories
= req
.body
['default-severity'];
309 return new Promise(function(resolve
, reject
) {
310 var promises
= Categories
.map(function(c
) {
311 return handleDeleteRequest(req
, APIVersion
+ '/api/config/logging/default-severity/' + c
.category
);
313 return Promise
.all(promises
).then(
325 // NOTE: In rel_4.3 we are going to affect syslog sink category by default
327 Config
.setDefaultSyslogSeverity = function(req
) {
328 // TODO: verify there is one key at root of data: 'default-severity'
329 // OR just filter on the request body
330 return handlePutRequest(req
, APIVersion
+ '/api/config/logging/sink/syslog');
333 Config
.deleteDefaultSyslogSeverity = function(req
) {
334 // TODO: verify there is one key at root of data: 'default-severity'
335 // OR just filter on the request body
336 var Categories
= req
.params
.nulledCategories
.split(',');
338 return new Promise(function(resolve
, reject
) {
339 promises
.concat(Categories
.map(function(categoryName
) {
340 return handleDeleteRequest(req
, APIVersion
+ '/api/config/logging/sink/syslog/filter/category/' + categoryName
);
342 return Promise
.all(promises
).then(
344 resolve({statusCode
: data
[0].statusCode
, data
: data
[0].data
});
347 reject({statusCode
: data
[0].statusCode
, data
: data
[0].data
});
357 "allowDuplicateEvents" : true
362 * TODO: Repeat delete calls (when 'allowDuplicateEvents' value is false) cause
364 * TODO: the call to handleDeleteRequest returns stringified data, but the PUT
365 * does not (This is the behavior we want)
367 * Improvement? Allos string representation of true/false
369 Config
.setAllowDuplicateEvents = function(req
) {
370 // TODO: verify there is one key at root of data: 'default-severity'
371 // OR just filter on the request body
372 console
.log(req
.body
)
373 if (req
.body
.hasOwnProperty('allowDuplicateEvents')) {
374 if (req
.body
.allowDuplicateEvents
.toUpperCase() == "TRUE") {
375 return handlePutRequest(req
, '/api/config/logging/allow', {
376 "duplicate": "events"
378 } else { // false, remove entry from logging config
379 return handleDeleteRequest(req
, '/api/config/logging/allow/duplicate');
382 return handleReject(statusCode
=400,
384 "message": 'Expected key, "allowDuplicateEvents" not found',
385 "original-request" : req
.body
408 Config
.setDenyEvents = function(req
) {
411 events
: req
.body
.denyEvents
.eventIDs
.map(function(eventID
) {
412 return { "event-Id": eventID
};
416 return handlePutRequest(req
, APIVersion
+ '/api/config/logging', reqBody
);
419 Config
.setSyslogViewer = function(req
) {
420 // TODO: Verify structure of req.body
422 "syslog-viewer" : req
.body
['syslog-viewer']
424 return handlePutRequest(req
, APIVersion
+ '/api/config/logging', reqBody
);
430 Operational
.get = function(req
) {
431 var APIVersion
= '/v1'
432 return handleGetRequest(req
, APIVersion
+ '/api/operational/logging?deep',
433 transformLoggingRootResponseCallback
439 * Legacy call to get sys log viewer
442 SysLogViewer
.get = function(req
) {
443 console
.log("\n***\n SysLogViewer.get called");
444 var api_server
= req
.query
['api_server'];
445 return new Promise(function(resolve
, reject
) {
447 uri
: utils
.confdPort(api_server
) + APIVersion
+ '/api/config/logging/syslog-viewer',
449 headers
: _
.extend({},
450 constants
.HTTP_HEADERS
.accept
.data
,
452 'Authorization': req
.get('Authorization')
455 rejectUnauthorized
: false
457 function(error
, response
, body
) {
459 console
.log('Logging.get failed. Error:', error
);
461 statusCode
: response
? response
.statusCode
: 404,
462 errorMessage
: 'Issue retrieving syslog-viewer url'
467 data
= JSON
.parse(response
.body
);
469 console
.log('Logging.get failed while parsing response.body. Error:', e
);
472 errorMessage
: 'Error parsing response.body during Logging.get'
484 Test
.roundtrip = function(req
) {
485 return new Promise(function(resolve
, reject
) {
486 Aggregate
.get(req
).then(function(result
) {
487 var data
= (new transforms
.LoggingConfigEncoder()).encode(result
.data
);
491 'rwlog-mgmt:logging': data
495 console
.log('Test.get error:', err
);
505 aggregate
: Aggregate
,
507 operational
: Operational
,
508 sysLogViewer
: SysLogViewer
,