Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GPII-3551: Improvements and bug fix for /ready and /health endpoint #713

Merged
merged 9 commits into from Dec 12, 2018
2 changes: 1 addition & 1 deletion gpii/node_modules/flowManager/src/HealthGetHandler.js
Expand Up @@ -26,5 +26,5 @@ fluid.defaults("gpii.health.handler", {
});

gpii.health.handleRequest = function (that) {
that.events.onSuccess.fire();
that.events.onSuccess.fire({isHealthy: true});
};
10 changes: 6 additions & 4 deletions gpii/node_modules/flowManager/src/PrefsServerDataSource.js
Expand Up @@ -15,6 +15,8 @@
var fluid = require("infusion"),
gpii = fluid.registerNamespace("gpii");

fluid.registerNamespace("gpii.flowManager.prefsServerDataSource");

// "gpii.flowManager.prefsServerDataSource" is used by the cloud based flow manager to communicate with the
// preferences server.
fluid.defaults("gpii.flowManager.prefsServerDataSource", {
Expand Down Expand Up @@ -140,10 +142,10 @@ gpii.flowManager.prefsServerDataSource.isLive = function (prefsServerHealthImpl)
var promiseTogo = fluid.promise();
var isLivePromise = prefsServerHealthImpl.get();

isLivePromise.then(function () {
promiseTogo.resolve(true);
}, function () {
promiseTogo.resolve(false);
isLivePromise.then(function (value) { // onResolve
promiseTogo.resolve(value);
}, function (value) { // onReject
promiseTogo.resolve(value);
});

return promiseTogo;
Expand Down
11 changes: 6 additions & 5 deletions gpii/node_modules/flowManager/src/ReadyGetHandler.js
Expand Up @@ -26,10 +26,11 @@ fluid.defaults("gpii.flowManager.cloudBased.ready.handler", {
});

gpii.flowManager.cloudBased.ready.handler.reportError = function (that, prefsServerURL) {
fluid.log ("Error connecting to Preferences Sever: '" + prefsServerURL + "'");
that.events.onError.fire({
isError: true,
message: "Cannot connect to Preferences Server at " + prefsServerURL,
statusCode: 404
message: "Error connecting to Preferences Server",
statusCode: 503
});
};

Expand All @@ -55,9 +56,9 @@ gpii.flowManager.cloudBased.ready.handler.isLive = function (prefsServerDataSour
gpii.flowManager.cloudBased.ready.handler.reportError(that, prefsServerDataSource.options.prefsServerURL);
} else {
var isLivePromise = prefsServerDataSource.isLive();
isLivePromise.then(function (isLive) {
if (isLive) {
that.events.onSuccess.fire();
isLivePromise.then(function (result) {
if (result.isReady) {
that.events.onSuccess.fire(result);
} else {
gpii.flowManager.cloudBased.ready.handler.reportError(that, prefsServerDataSource.options.prefsServerURL);
}
Expand Down
13 changes: 8 additions & 5 deletions gpii/node_modules/flowManager/test/PrefsServerDataSourceTests.js
Expand Up @@ -57,9 +57,12 @@ gpii.tests.prefsServerDataSource.nockConfig = {
merge: true
}
},
health: {
ready: {
url: gpii.tests.prefsServerDataSource.readyUrl,
status: 200
status: 200,
response: {
isReady: true
}
}
};

Expand All @@ -78,9 +81,9 @@ gpii.tests.prefsServerDataSource.setUpNock = function (config) {
cloudMock.put(config.preferencesPut.url, gpii.tests.prefsServerDataSource.preferences)
.reply(config.preferencesPut.status, config.preferencesPut.response);

// mock GET requests to "/health"
cloudMock.get(config.health.url)
.reply(config.health.status);
// mock GET requests to "/ready"
cloudMock.get(config.ready.url)
.reply(config.ready.status, config.ready.response);
};

// The customized prefsServerDataSource component for tests
Expand Down
10 changes: 8 additions & 2 deletions gpii/node_modules/gpii-db-operation/src/DbDataStore.js
Expand Up @@ -125,6 +125,12 @@ fluid.defaults("gpii.dbOperation.dbDataStore", {
}
}
},
findAllViewsDataSource: {
type: "gpii.dbOperation.dbDataSource",
options: {
requestUrl: "/_design/views"
}
},
findAuthorizationByAccessTokenDataSource: {
type: "gpii.dbOperation.dbDataSource",
options: {
Expand Down Expand Up @@ -210,8 +216,8 @@ fluid.defaults("gpii.dbOperation.dbDataStore", {
// accessToken
},
findAllViews: {
func: "{that}.findById",
args: ["_design/views"]
funcName: "gpii.dbOperation.dbDataStore.findRecord",
args: ["{that}.findAllViewsDataSource"]
},
addGpiiKey: {
funcName: "gpii.dbOperation.dbDataStore.addGpiiKey",
Expand Down
15 changes: 8 additions & 7 deletions gpii/node_modules/gpii-db-operation/src/DbDataStoreUtils.js
Expand Up @@ -15,7 +15,8 @@ https://github.com/GPII/universal/blob/master/LICENSE.txt
var fluid = fluid || require("infusion"),
gpii = fluid.registerNamespace("gpii"),
$ = fluid.registerNamespace("jQuery"),
uuid = uuid || require("node-uuid");
uuid = uuid || require("node-uuid"),
urlModule = urlModule || require("url");

fluid.registerNamespace("gpii.dbOperation.dbDataStore");

Expand All @@ -42,7 +43,8 @@ gpii.dbOperation.dbDataStore.findRecord = function (dataSource, directModel, val

if (emptyFields.length > 0) {
var error = gpii.dbOperation.composeError(gpii.dbOperation.errors.missingInput, {fieldName: emptyFields.join(" & ")});
promiseTogo.reject(error);
fluid.log("gpii-db-operation, findRecord(), error: ", error);
promiseTogo.reject(error); // reject #1 of 3.
} else {
var finalDirectModel = fluid.extend(true, {}, dataSource.options.directModel, directModel);
var promise = dataSource.get(finalDirectModel);
Expand All @@ -61,16 +63,15 @@ gpii.dbOperation.dbDataStore.findRecord = function (dataSource, directModel, val
// by a document id, 404 status is returned and this conversion is not needed.
var result = $.isEmptyObject(data) ? undefined : dataProcessFunc(data);
if (result !== undefined && result.isError) {
promiseTogo.reject(result);
promiseTogo.reject(result); // reject #2 of 3.
} else {
promiseTogo.resolve(result);
promiseTogo.resolve(result); // result can be undefined.
}
}, function (error) {
fluid.log("gpii-db-operation, findRecord(), error occurs: ", error);
promiseTogo.reject(error);
fluid.log("gpii-db-operation, findRecord(), error: ", error);
promiseTogo.reject(error); // reject #3 of 3.
});
}

return promiseTogo;
};

Expand Down
13 changes: 8 additions & 5 deletions gpii/node_modules/preferencesServer/src/preferencesService.js
Expand Up @@ -360,17 +360,20 @@ var fluid = fluid || require("infusion");
};

/**
* Verify if the preference server is running and the database connection is good.
* @param {Function} findAllViews - The findAllViews() API provided by gpii.oauth2.dbDataStore
* @return {Boolean} return true if the database connection is ok. Otherwise, return false.
* Verify if the preference server is running and the database connection is
* good.
* @param {Function} findAllViews - The findAllViews() API provided by
* gpii.oauth2.dbDataStore
* @return {Promise} resolves to {isReady: true} if the database connection
* is ok. Otherwise, resolves to {isReady: false}.
*/
gpii.preferencesServer.preferencesService.isLive = function (findAllViews) {
var promiseTogo = fluid.promise();
var viewsPromise = findAllViews();
viewsPromise.then(function (views) {
promiseTogo.resolve(fluid.isPlainObject(views));
promiseTogo.resolve({isReady: fluid.isPlainObject(views)});
}, function () {
promiseTogo.resolve(false);
promiseTogo.resolve({isReady: false});
});
return promiseTogo;
};
Expand Down
12 changes: 6 additions & 6 deletions gpii/node_modules/preferencesServer/src/readyGetHandler.js
Expand Up @@ -28,20 +28,20 @@ fluid.defaults("gpii.preferencesServer.ready.handler", {
gpii.preferencesServer.ready.handler.reportError = function (request) {
request.events.onError.fire({
isError: true,
message: "Problem with the database connection.",
statusCode: 404
message: "Problem with the database connection",
statusCode: 503
});
};

gpii.preferencesServer.ready.handler.getPreferences = function (preferencesServer, request) {
var isLivePromise = preferencesServer.preferencesService.isLive();
isLivePromise.then(function (isLive) {
if (isLive) {
request.events.onSuccess.fire();
isLivePromise.then(function (value) { // onResolve
if (value.isReady) {
request.events.onSuccess.fire(value);
} else {
gpii.preferencesServer.ready.handler.reportError(request);
}
}, function () {
}, function () { // onReject
gpii.preferencesServer.ready.handler.reportError(request);
});
};
Expand Up @@ -1541,7 +1541,7 @@ fluid.transform(gpii.tests.preferencesServer.ready.testDefsWithoutDbConnection,
}, {
event: "{serverStatusRequest}.events.onComplete",
listener: "jqUnit.assertEquals",
args: ["Receives http status code 404", 404, "{serverStatusRequest}.nativeResponse.statusCode"]
args: ["Receives http status code 503", 503, "{serverStatusRequest}.nativeResponse.statusCode"]
}]
});
});
Expand Down
46 changes: 34 additions & 12 deletions tests/platform/cloud/CloudStatusTests.js
Expand Up @@ -12,7 +12,8 @@ https://github.com/GPII/universal/blob/master/LICENSE.txt
"use strict";

var fluid = require("infusion"),
gpii = fluid.registerNamespace("gpii");
gpii = fluid.registerNamespace("gpii"),
jqUnit = fluid.registerNamespace("jqUnit");

fluid.require("%gpii-universal");

Expand All @@ -36,9 +37,10 @@ gpii.tests.cloudStatus.configs = {
};

gpii.tests.cloudStatus.commonTestDefs = {
expect: 1,
expect: 2,
testUrl: null, // provided by each test run
expectedStatusCode: 200, // provided by each test run
expectedPayload: {}, // provided by each test run
distributeOptions: {
source: "{that}.options.testUrl",
target: "{that > serverStatusRequest}.options.path"
Expand All @@ -56,58 +58,78 @@ gpii.tests.cloudStatus.commonTestDefs = {
func: "{serverStatusRequest}.send"
}, {
event: "{serverStatusRequest}.events.onComplete",
listener: "jqUnit.assertEquals",
args: ["Receives http status code 200", "{that}.options.expectedStatusCode", "{serverStatusRequest}.nativeResponse.statusCode"]
listener: "gpii.tests.cloudStatus.testResponse",
args: [
"{that}.options.expectedStatusCode",
"{that}.options.expectedPayload",
"{serverStatusRequest}.nativeResponse.statusCode",
"{arguments}.0" // response payload
]
}]
};

gpii.tests.cloudStatus.testResponse = function (expectedStatus, expectedPayload, actualStatus, actualPayload) {
jqUnit.assertEquals("Checking http status code", expectedStatus, actualStatus);
jqUnit.assertDeepEq("Checking payload", expectedPayload, JSON.parse(actualPayload));
};

gpii.tests.cloudStatus.testCases = {
// Test cases for /health
testReadyWithAllUp: {
name: "Test the readiness of the cloud based flow manager: all local with both the cloud based flow manager and the prefs server up running",
url: "/health",
config: gpii.tests.cloudStatus.configs.allLocalWithPrefsServer,
expectedStatusCode: 200
expectedStatusCode: 200,
expectedPayload: {"isHealthy": true}
},
testReadyWithoutPrefsServer: {
name: "Test the readiness of the cloud based flow manager: all local with only the cloud based flow manager running",
url: "/health",
config: gpii.tests.cloudStatus.configs.allLocalWithoutPrefsServer,
expectedStatusCode: 200
expectedStatusCode: 200,
expectedPayload: {"isHealthy": true}
},
testReadyWithSeparateServers: {
name: "Test the readiness of the cloud based flow manager: the cloud based flow manager and the prefs server run as separate servers",
url: "/health",
config: gpii.tests.cloudStatus.configs.separateServersWithPrefsServer,
expectedStatusCode: 200
expectedStatusCode: 200,
expectedPayload: {"isHealthy": true}
},

// Test cases for /ready
testHealthWithAllUp: {
name: "Test the liveness of the cloud based flow manager: all local with both the cloud based flow manager and the prefs server up running",
url: "/ready",
config: gpii.tests.cloudStatus.configs.allLocalWithPrefsServer,
expectedStatusCode: 200
expectedStatusCode: 200,
expectedPayload: {"isReady": true}
},
testHealthWithoutPrefsServer: {
name: "Test the liveness of the cloud based flow manager: all local with only the cloud based flow manager running",
url: "/ready",
config: gpii.tests.cloudStatus.configs.allLocalWithoutPrefsServer,
expectedStatusCode: 404
expectedStatusCode: 503,
expectedPayload: {
"isError": true,
"message": "Error connecting to Preferences Server"
}
},
testHealthWithSeparateServers: {
name: "Test the liveness of the cloud based flow manager: the cloud based flow manager and the prefs server run as separate servers",
url: "/ready",
config: gpii.tests.cloudStatus.configs.separateServersWithPrefsServer,
expectedStatusCode: 200
expectedStatusCode: 200,
expectedPayload: {"isReady": true}
}
};

fluid.each(gpii.tests.cloudStatus.testCases, function (oneCase) {
var oneTestDef = fluid.extend(true, gpii.tests.cloudStatus.commonTestDefs, {
var oneTestDef = fluid.extend(true, {}, gpii.tests.cloudStatus.commonTestDefs, {
name: oneCase.name,
testUrl: oneCase.url,
expectedStatusCode: oneCase.expectedStatusCode
expectedStatusCode: oneCase.expectedStatusCode,
expectedPayload: oneCase.expectedPayload
}, {
config: oneCase.config
});
Expand Down