This is an automated email from the ASF dual-hosted git repository. csantanapr pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk-package-cloudant.git
The following commit(s) were added to refs/heads/master by this push: new 44e6613 Trigger management (#137) 44e6613 is described below commit 44e6613301af0d8b80e9341ae0dc726dafb7169f Author: Adnan Baruni <abar...@users.noreply.github.com> AuthorDate: Tue Oct 31 14:54:48 2017 -0500 Trigger management (#137) * implementation of trigger management get status and configuration, tests * formatting * remove trailing whitespace * fix scanCode complaint * update dateChanged field to millis since epoch to provide consistency * remove maxTriggers from response, add dateChangedISO to response --- actions/changes.js | 18 ++- actions/changesWebAction.js | 56 ++++++- provider/lib/utils.js | 2 +- .../scala/system/packages/CloudantFeedTests.scala | 167 ++++++++++++++++++++- 4 files changed, 233 insertions(+), 10 deletions(-) diff --git a/actions/changes.js b/actions/changes.js index 7115024..41c03a2 100644 --- a/actions/changes.js +++ b/actions/changes.js @@ -2,7 +2,14 @@ var request = require('request'); function main(msg) { + let eventMap = { + CREATE: 'put', + READ: 'get', + // UPDATE: 'put', + DELETE: 'delete' + }; // for creation -> CREATE + // for reading -> READ // for deletion -> DELETE var lifecycleEvent = msg.lifecycleEvent; @@ -11,12 +18,11 @@ function main(msg) { var url = `https://${endpoint}/api/v1/web/whisk.system/cloudantWeb/changesWebAction.http`; - if (lifecycleEvent !== 'CREATE' && lifecycleEvent !== 'DELETE') { - return Promise.reject('lifecycleEvent must be CREATE or DELETE'); - } - else { - var method = lifecycleEvent === 'CREATE' ? 'put' : 'delete'; + if (lifecycleEvent in eventMap) { + var method = eventMap[lifecycleEvent]; return requestHelper(url, webparams, method); + } else { + return Promise.reject('unsupported lifecycleEvent'); } } @@ -32,7 +38,7 @@ function requestHelper(url, input, method) { }, function(error, response, body) { if (!error && response.statusCode === 200) { - resolve(); + resolve(body); } else { if (response) { diff --git a/actions/changesWebAction.js b/actions/changesWebAction.js index 1899dd3..8a405e2 100644 --- a/actions/changesWebAction.js +++ b/actions/changesWebAction.js @@ -1,4 +1,5 @@ var request = require('request'); +var moment = require('moment'); function main(params) { @@ -68,7 +69,7 @@ function main(params) { query_params: query_params, status: { 'active': true, - 'dateChanged': new Date().toISOString() + 'dateChanged': Date.now() } }; @@ -98,6 +99,45 @@ function main(params) { }); } + else if (params.__ow_method === "get") { + return new Promise(function (resolve, reject) { + verifyTriggerAuth(triggerURL, params.authKey, false) + .then(() => { + return getTrigger(db, triggerID); + }) + .then(doc => { + var body = { + config: { + name: doc.id.split(':')[2], + namespace: doc.id.split(':')[1], + host: doc.host, + port: doc.port, + protocol: doc.protocol, + dbname: doc.dbname, + username: doc.user, + password: doc.pass, + since: doc.since, + filter: doc.filter, + query_params: doc.query_params, + }, + status: { + active: doc.status.active, + dateChanged: moment(doc.status.dateChanged).utc().valueOf(), + dateChangedISO: moment(doc.status.dateChanged).utc().format(), + reason: doc.status.reason + } + }; + resolve({ + statusCode: 200, + headers: {'Content-Type': 'application/json'}, + body: new Buffer(JSON.stringify(body)).toString('base64') + }); + }) + .catch(err => { + reject(err); + }); + }); + } else if (params.__ow_method === "delete") { return new Promise(function (resolve, reject) { @@ -178,6 +218,20 @@ function createTrigger(triggerDB, triggerID, newTrigger) { }); } +function getTrigger(triggerDB, triggerID) { + + return new Promise(function(resolve, reject) { + + triggerDB.get(triggerID, function (err, existing) { + if (err) { + reject(err); + } else { + resolve(existing); + } + }); + }); +} + function updateTrigger(triggerDB, triggerID, retryCount) { return new Promise(function(resolve, reject) { diff --git a/provider/lib/utils.js b/provider/lib/utils.js index ea6d906..f22909b 100644 --- a/provider/lib/utils.js +++ b/provider/lib/utils.js @@ -133,7 +133,7 @@ module.exports = function( var updatedTrigger = existing; var status = { 'active': false, - 'dateChanged': new Date().toISOString(), + 'dateChanged': Date.now(), 'reason': {'kind': 'AUTO', 'statusCode': statusCode, 'message': message} }; updatedTrigger.status = status; diff --git a/tests/src/test/scala/system/packages/CloudantFeedTests.scala b/tests/src/test/scala/system/packages/CloudantFeedTests.scala index 3ed99cd..ef6ba84 100644 --- a/tests/src/test/scala/system/packages/CloudantFeedTests.scala +++ b/tests/src/test/scala/system/packages/CloudantFeedTests.scala @@ -19,9 +19,9 @@ package system.packages import common.TestUtils.ANY_ERROR_EXIT import common._ import org.junit.runner.RunWith -import org.scalatest.FlatSpec +import org.scalatest.{FlatSpec, Inside} import org.scalatest.junit.JUnitRunner -import spray.json.DefaultJsonProtocol.{IntJsonFormat, StringJsonFormat} +import spray.json.DefaultJsonProtocol.{IntJsonFormat, StringJsonFormat, BooleanJsonFormat} import spray.json.{JsObject, JsString, pimpAny} import system.CloudantUtil @@ -32,6 +32,7 @@ import system.CloudantUtil class CloudantFeedTests extends FlatSpec with TestHelpers + with Inside with WskTestHelpers with WskActorSystem { @@ -324,4 +325,166 @@ class CloudantFeedTests } } + it should "return correct status and configuration" in withAssetCleaner(wskprops) { + val currentTime = s"${System.currentTimeMillis}" + + (wp, assetHelper) => + implicit val wskProps = wp + val triggerName = s"dummyCloudantTrigger-${System.currentTimeMillis}" + val packageName = "dummyCloudantPackage" + val feed = "changes" + + try { + CloudantUtil.setUp(myCloudantCreds) + + // the package alarms should be there + val packageGetResult = wsk.pkg.get("/whisk.system/cloudant") + println("fetched package cloudant") + packageGetResult.stdout should include("ok") + + // create package binding + assetHelper.withCleaner(wsk.pkg, packageName) { + (pkg, name) => pkg.bind("/whisk.system/cloudant", name) + } + + val username = myCloudantCreds.user + val password = myCloudantCreds.password + val host = myCloudantCreds.host() + val dbName = myCloudantCreds.dbname + val port = 443 + val protocol = "https" + val since = "now" + val filter = "test_filter/fruit" + val queryParams = JsObject("type" -> JsString("tomato")) + + // create whisk stuff + val feedCreationResult = assetHelper.withCleaner(wsk.trigger, triggerName, confirmDelete = false) { + (trigger, name) => + trigger.create(name, feed = Some(s"$packageName/$feed"), parameters = Map( + "username" -> username.toJson, + "password" -> password.toJson, + "host" -> host.toJson, + "dbname" -> dbName.toJson, + "filter" -> filter.toJson, + "query_params" -> queryParams, + "protocol" -> protocol.toJson, + "port" -> port.toJson, + "since" -> since.toJson + )) + } + feedCreationResult.stdout should include("ok") + + val actionName = s"$packageName/$feed" + val run = wsk.action.invoke(actionName, parameters = Map( + "triggerName" -> triggerName.toJson, + "lifecycleEvent" -> "READ".toJson, + "authKey" -> wskProps.authKey.toJson + )) + + withActivation(wsk.activation, run) { + activation => + activation.response.success shouldBe true + + inside(activation.response.result) { + case Some(result) => + val config = result.getFields("config").head.asInstanceOf[JsObject].fields + val status = result.getFields("status").head.asInstanceOf[JsObject].fields + + config should contain("name" -> triggerName.toJson) + config should contain("username" -> username.toJson) + config should contain("password" -> password.toJson) + config should contain("dbname" -> dbName.toJson) + config should contain("filter" -> filter.toJson) + config should contain("query_params" -> queryParams) + config should contain("protocol" -> protocol.toJson) + config should contain("port" -> port.toJson) + config should contain("since" -> since.toJson) + config should contain key "namespace" + + status should contain("active" -> true.toJson) + status should contain key "dateChanged" + status should contain key "dateChangedISO" + status should not(contain key "reason") + } + } + } finally { + CloudantUtil.unsetUp(myCloudantCreds) + } + + } + + it should "not return fields in configuration that are not passed in during trigger create" in withAssetCleaner(wskprops) { + val currentTime = s"${System.currentTimeMillis}" + + (wp, assetHelper) => + implicit val wskProps = wp + val triggerName = s"dummyCloudantTrigger-${System.currentTimeMillis}" + val packageName = "dummyCloudantPackage" + val feed = "changes" + + try { + CloudantUtil.setUp(myCloudantCreds) + + // the package alarms should be there + val packageGetResult = wsk.pkg.get("/whisk.system/cloudant") + println("fetched package cloudant") + packageGetResult.stdout should include("ok") + + // create package binding + assetHelper.withCleaner(wsk.pkg, packageName) { + (pkg, name) => pkg.bind("/whisk.system/cloudant", name) + } + + val username = myCloudantCreds.user + val password = myCloudantCreds.password + val host = myCloudantCreds.host() + val dbName = myCloudantCreds.dbname + + // create whisk stuff + val feedCreationResult = assetHelper.withCleaner(wsk.trigger, triggerName, confirmDelete = false) { + (trigger, name) => + trigger.create(name, feed = Some(s"$packageName/$feed"), parameters = Map( + "username" -> username.toJson, + "password" -> password.toJson, + "host" -> host.toJson, + "dbname" -> dbName.toJson + )) + } + feedCreationResult.stdout should include("ok") + + val actionName = s"$packageName/$feed" + val run = wsk.action.invoke(actionName, parameters = Map( + "triggerName" -> triggerName.toJson, + "lifecycleEvent" -> "READ".toJson, + "authKey" -> wskProps.authKey.toJson + )) + + withActivation(wsk.activation, run) { + activation => + activation.response.success shouldBe true + + inside(activation.response.result) { + case Some(result) => + val config = result.getFields("config").head.asInstanceOf[JsObject].fields + + config should contain key "username" + config should contain key "password" + config should contain key "host" + config should contain key "dbname" + + config should not { + contain key "query_params" + contain key "filter" + contain key "protocol" + contain key "since" + contain key "port" + } + } + } + } finally { + CloudantUtil.unsetUp(myCloudantCreds) + } + + } + } -- To stop receiving notification emails like this one, please contact ['"commits@openwhisk.apache.org" <commits@openwhisk.apache.org>'].