You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwhisk.apache.org by cs...@apache.org on 2017/10/31 19:54:53 UTC

[incubator-openwhisk-package-cloudant] branch master updated: Trigger management (#137)

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 <ab...@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" <co...@openwhisk.apache.org>'].