mdeuser closed pull request #3187: reduce rule activation records
URL: https://github.com/apache/incubator-openwhisk/pull/3187
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git 
a/core/controller/src/main/scala/whisk/core/controller/Triggers.scala 
b/core/controller/src/main/scala/whisk/core/controller/Triggers.scala
index 3893f57a4f..7b6d41f4f9 100644
--- a/core/controller/src/main/scala/whisk/core/controller/Triggers.scala
+++ b/core/controller/src/main/scala/whisk/core/controller/Triggers.scala
@@ -22,6 +22,7 @@ import java.time.{Clock, Instant}
 import akka.actor.ActorSystem
 import akka.http.scaladsl.Http
 import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
+import akka.http.scaladsl.model.ContentTypes
 import akka.http.scaladsl.model.HttpMethods.POST
 import akka.http.scaladsl.model.StatusCodes._
 import akka.http.scaladsl.model.{HttpEntity, HttpRequest, MediaTypes, Uri}
@@ -37,7 +38,9 @@ import whisk.core.database.CacheChangeNotification
 import whisk.core.entitlement.Collection
 import whisk.core.entity._
 import whisk.core.entity.types.{ActivationStore, EntityStore}
+import whisk.http.ErrorResponse
 
+import scala.collection.immutable.Map
 import scala.concurrent.Future
 
 /** A trait implementing the triggers API. */
@@ -63,6 +66,7 @@ trait WhiskTriggersApi extends WhiskCollectionAPI {
 
   /** Path to Triggers REST API. */
   protected val triggersPath = "triggers"
+  protected val url = Uri(s"http://localhost:${whiskConfig.servicePort}";)
 
   protected implicit val materializer: ActorMaterializer
 
@@ -107,10 +111,8 @@ trait WhiskTriggersApi extends WhiskCollectionAPI {
     entity(as[Option[JsObject]]) { payload =>
       getEntity(WhiskTrigger, entityStore, entityName.toDocId, Some {
         trigger: WhiskTrigger =>
-          val args = trigger.parameters.merge(payload)
           val triggerActivationId = activationIdFactory.make()
           logging.info(this, s"[POST] trigger activation id: 
${triggerActivationId}")
-
           val triggerActivation = WhiskActivation(
             namespace = user.namespace.toPath, // all activations should end 
up in the one space regardless trigger.namespace,
             entityName.name,
@@ -122,72 +124,133 @@ trait WhiskTriggersApi extends WhiskCollectionAPI {
             version = trigger.version,
             duration = None)
 
-          logging.info(this, s"[POST] trigger activated, writing activation 
record to datastore: $triggerActivationId")
-          WhiskActivation.put(activationStore, triggerActivation) recover {
-            case t =>
-              logging.error(this, s"[POST] storing trigger activation 
$triggerActivationId failed: ${t.getMessage}")
-          }
-
-          val url = Uri(s"http://localhost:${whiskConfig.servicePort}";)
-
-          trigger.rules.map {
-            _.filter {
-              case (ruleName, rule) => rule.status == Status.ACTIVE
-            } foreach {
-              case (ruleName, rule) =>
-                val ruleActivationId = activationIdFactory.make()
-                val ruleActivation = WhiskActivation(
-                  namespace = user.namespace.toPath, // all activations should 
end up in the one space regardless trigger.namespace,
-                  ruleName.name,
-                  user.subject,
-                  ruleActivationId,
-                  Instant.now(Clock.systemUTC()),
-                  Instant.EPOCH,
-                  cause = Some(triggerActivationId),
-                  response = ActivationResponse.success(),
-                  version = trigger.version,
-                  duration = None)
-                WhiskActivation.put(activationStore, ruleActivation) recover {
-                  case t =>
-                    logging.error(this, s"[POST] storing rule activation 
$ruleActivationId failed: ${t.getMessage}")
-                }
-
-                val actionNamespace = rule.action.path.root.asString
-                val actionPath = {
-                  rule.action.path.relativePath.map { pkg =>
-                    (Path.SingleSlash + pkg.namespace) / 
rule.action.name.asString
-                  } getOrElse {
-                    Path.SingleSlash + rule.action.name.asString
-                  }
-                }.toString
-
-                val actionUrl = Path("/api/v1") / "namespaces" / 
actionNamespace / "actions"
-                val request = HttpRequest(
-                  method = POST,
-                  uri = url.withPath(actionUrl + actionPath),
-                  headers =
-                    
List(Authorization(BasicHttpCredentials(user.authkey.uuid.asString, 
user.authkey.key.asString))),
-                  entity = HttpEntity(MediaTypes.`application/json`, 
args.getOrElse(JsObject()).compactPrint))
-
-                Http().singleRequest(request).map {
-                  response =>
-                    response.status match {
-                      case OK | Accepted =>
-                        Unmarshal(response.entity).to[JsObject].map { a =>
-                          logging.info(this, s"${rule.action} activated 
${a.fields("activationId")}")
-                        }
-                      case NotFound =>
-                        response.discardEntityBytes()
-                        logging.info(this, s"${rule.action} failed, action not 
found")
-                      case _ =>
-                        Unmarshal(response.entity).to[String].map { error =>
-                          logging.warn(this, s"${rule.action} failed due to 
$error")
+          // List of active rules associated with the trigger
+          val activeRules = trigger.rules map { _.filter((r) => r._2.status == 
Status.ACTIVE) } getOrElse Map.empty
+
+          if (activeRules.nonEmpty) {
+            val args = trigger.parameters.merge(payload)
+
+            // Iterate through each active rule; invoking each mapped action
+            val actionLogList = activeRules
+              .map {
+                case (ruleName, rule) =>
+                  // Build the url to invoke an action mapped to the rule
+                  val actionNamespace = rule.action.path.root.asString
+                  val actionPath = {
+                    rule.action.path.relativePath.map { pkg =>
+                      (Path.SingleSlash + pkg.namespace) / 
rule.action.name.asString
+                    } getOrElse {
+                      Path.SingleSlash + rule.action.name.asString
+                    }
+                  }.toString
+
+                  val actionUrl = Path("/api/v1/namespaces") / actionNamespace 
/ "actions"
+                  val request = HttpRequest(
+                    method = POST,
+                    uri = url.withPath(actionUrl + actionPath),
+                    headers =
+                      
List(Authorization(BasicHttpCredentials(user.authkey.uuid.asString, 
user.authkey.key.asString))),
+                    entity = HttpEntity(MediaTypes.`application/json`, 
args.getOrElse(JsObject()).compactPrint))
+
+                  // Invoke the action. Retain action results for inclusion in 
the trigger activation record
+                  Http()
+                    .singleRequest(request)
+                    .flatMap {
+                      response =>
+                        response.status match {
+                          case OK | Accepted =>
+                            Unmarshal(response.entity).to[JsObject].map { a =>
+                              logging.info(
+                                this,
+                                s"trigger-fired action '${rule.action}' 
invoked with activation ${a.fields("activationId")}")
+                              (ruleName.asString -> ruleResult(
+                                ActivationResponse.Success,
+                                ruleName.asString,
+                                rule.action.asString,
+                                
Some(a.fields("activationId").replaceAll("^\"|\"$", ""))))
+                            }
+                          case NotFound =>
+                            logging.info(this, s"trigger-fired action 
'${rule.action}' not found")
+                            Unmarshal(response.entity)
+                              .to[ErrorResponse]
+                              .map(
+                                e =>
+                                  (ruleName.asString -> ruleResult(
+                                    ActivationResponse.ApplicationError,
+                                    ruleName.asString,
+                                    rule.action.asString,
+                                    errorMsg = Some(e.error))))
+                          case _ =>
+                            logging.info(this, s"trigger-fired action 
'${rule.action}' response unknown")
+                            if (response.entity.contentType == 
ContentTypes.`application/json`) {
+                              Unmarshal(response.entity)
+                                .to[ErrorResponse]
+                                .map(
+                                  e =>
+                                    (ruleName.asString -> ruleResult(
+                                      ActivationResponse.WhiskError,
+                                      ruleName.asString,
+                                      rule.action.asString,
+                                      errorMsg = Some(e.error))))
+                            } else {
+                              Unmarshal(response.entity).to[String].map { 
error =>
+                                (ruleName.asString -> ruleResult(
+                                  ActivationResponse.WhiskError,
+                                  ruleName.asString,
+                                  rule.action.asString,
+                                  errorMsg = Some(error)))
+                              }
+                            }
                         }
                     }
-                }
-            }
+                    .recover {
+                      case ex =>
+                        logging.error(this, s"trigger-fired action 
'${rule.action}' invocation failure: $ex")
+                        (ruleName.asString -> ruleResult(
+                          ActivationResponse.WhiskError,
+                          ruleName.asString,
+                          rule.action.asString,
+                          errorMsg = Some(ex.toString)))
+                    }
+              }
+
+            // To write out activation logs, need to convert the action result 
list
+            // of tuples into a vector of strings.  Convert 
List[Future[(String, JsObject)]] => Future[Vector(String)]
+            val triggerLogs = Future
+              .sequence(actionLogList)
+              .map { tupleList =>
+                tupleList
+                  .map {
+                    case (ruleName, ruleResultJsObj) => 
ruleResultJsObj.compactPrint
+                  }
+                  .to[Vector]
+              }
+              .onComplete {
+                case scala.util.Success(triggerLogs) =>
+                  logging.info(this, s"Writing action activation results to 
trigger activation")
+                  val triggerActivationDoc = 
triggerActivation.withLogs(ActivationLogs(triggerLogs))
+                  logging
+                    .info(
+                      this,
+                      s"[POST] trigger activated, writing activation record to 
datastore: $triggerActivationId")
+                  WhiskActivation.put(activationStore, triggerActivationDoc) 
recover {
+                    case t =>
+                      logging
+                        .error(this, s"[POST] storing trigger activation 
$triggerActivationId failed: ${t.getMessage}")
+                  }
+                case scala.util.Failure(e) =>
+                  logging.error(this, s"Failed to write action activation 
results to trigger activation: $e")
+                  logging
+                    .info(
+                      this,
+                      s"[POST] trigger activated, writing activation record to 
datastore: $triggerActivationId")
+                  WhiskActivation.put(activationStore, triggerActivation) 
recover {
+                    case t =>
+                      logging
+                        .error(this, s"[POST] storing trigger activation 
$triggerActivationId failed: ${t.getMessage}")
+                  }
+              }
           }
-
           complete(Accepted, triggerActivationId.toJsObject)
       })
     }
@@ -326,6 +389,47 @@ trait WhiskTriggersApi extends WhiskCollectionAPI {
     complete(OK, trigger.withoutRules)
   }
 
+  /**
+   * Create JSON object containing the pertinent rule activation details
+   *
+   * @param statusCode
+   * @param ruleName
+   * @param actionName
+   * @param actionActivationId
+   * @param msg
+   * @return
+   */
+  private def ruleResult(statusCode: Int,
+                         ruleName: String,
+                         actionName: String,
+                         actionActivationId: Option[String] = None,
+                         errorMsg: Option[String] = None): JsObject = {
+    val objMap: Map[String, JsValue] = Map(
+      "rule" -> JsString(ruleName),
+      "action" -> JsString(actionName),
+      "statusCode" -> JsNumber(statusCode),
+      "success" -> JsBoolean(statusCode == ActivationResponse.Success)) ++ {
+      actionActivationId map { id =>
+        Seq("activationId" -> JsString(id))
+      } getOrElse Seq()
+    } ++ {
+      errorMsg map { err =>
+        Seq("error" -> JsString(err))
+      } getOrElse Seq()
+    }
+
+    // Final rule result looks like
+    // {
+    //   "rule": "my-rule",
+    //   "action": "my-action",
+    //   "statusCode": 0,
+    //   "status": "success",
+    //   "activationId": "90c84e7b33c84ceb884e7b33c8ecebf6",  // Optional
+    //   "error": "The requested resource does not exist."  // Optional
+    // }
+    JsObject(objMap)
+  }
+
   /** Custom unmarshaller for query parameters "limit" for "list" operations. 
*/
   private implicit val stringToListLimit: Unmarshaller[String, ListLimit] = 
RestApiCommons.stringToListLimit(collection)
 }
diff --git a/tests/src/test/scala/system/basic/WskBasicTests.scala 
b/tests/src/test/scala/system/basic/WskBasicTests.scala
index e51f5f328a..fd7397bb75 100644
--- a/tests/src/test/scala/system/basic/WskBasicTests.scala
+++ b/tests/src/test/scala/system/basic/WskBasicTests.scala
@@ -45,6 +45,11 @@ class WskBasicTests extends TestHelpers with WskTestHelpers {
   val wsk = new Wsk
   val defaultAction = Some(TestUtils.getTestActionFilename("hello.js"))
 
+  /**
+   * Append the current timestamp in ms
+   */
+  def withTimestamp(text: String) = s"${text}-${System.currentTimeMillis}"
+
   behavior of "Wsk CLI"
 
   it should "reject creating duplicate entity" in withAssetCleaner(wskprops) { 
(wp, assetHelper) =>
@@ -464,34 +469,50 @@ class WskBasicTests extends TestHelpers with 
WskTestHelpers {
   behavior of "Wsk Trigger CLI"
 
   it should "create, update, get, fire and list trigger" in 
withAssetCleaner(wskprops) { (wp, assetHelper) =>
-    val name = "listTriggers"
+    val ruleName = withTimestamp("r1toa1")
+    val triggerName = withTimestamp("t1tor1")
+    val actionName = withTimestamp("a1")
     val params = Map("a" -> "A".toJson)
-    assetHelper.withCleaner(wsk.trigger, name) { (trigger, _) =>
-      trigger.create(name, parameters = params)
-      trigger.create(name, update = true)
+
+    assetHelper.withCleaner(wsk.trigger, triggerName) { (trigger, _) =>
+      trigger.create(triggerName, parameters = params)
+      trigger.create(triggerName, update = true)
+    }
+
+    assetHelper.withCleaner(wsk.action, actionName) { (action, name) =>
+      action.create(name, defaultAction)
     }
-    val stdout = wsk.trigger.get(name).stdout
+
+    assetHelper.withCleaner(wsk.rule, ruleName) { (rule, name) =>
+      rule.create(name, trigger = triggerName, action = actionName)
+    }
+
+    val stdout = wsk.trigger.get(triggerName).stdout
     stdout should include regex (""""key": "a"""")
     stdout should include regex (""""value": "A"""")
     stdout should include regex (""""publish": false""")
     stdout should include regex (""""version": "0.0.2"""")
 
     val dynamicParams = Map("t" -> "T".toJson)
-    val run = wsk.trigger.fire(name, dynamicParams)
+    val run = wsk.trigger.fire(triggerName, dynamicParams)
     withActivation(wsk.activation, run) { activation =>
       activation.response.result shouldBe Some(dynamicParams.toJson)
       activation.duration shouldBe 0L // shouldn't exist but CLI generates it
       activation.end shouldBe Instant.EPOCH // shouldn't exist but CLI 
generates it
+      activation.logs shouldBe defined
+      val logs = activation.logs.get.toString
+      logs should include("activationId")
+      logs should include(""""statusCode":0""")
     }
 
-    val runWithNoParams = wsk.trigger.fire(name, Map())
+    val runWithNoParams = wsk.trigger.fire(triggerName, Map())
     withActivation(wsk.activation, runWithNoParams) { activation =>
       activation.response.result shouldBe Some(JsObject())
       activation.duration shouldBe 0L // shouldn't exist but CLI generates it
       activation.end shouldBe Instant.EPOCH // shouldn't exist but CLI 
generates it
     }
 
-    wsk.trigger.list().stdout should include(name)
+    wsk.trigger.list().stdout should include(triggerName)
   }
 
   it should "create, and get a trigger summary" in withAssetCleaner(wskprops) 
{ (wp, assetHelper) =>
@@ -523,17 +544,26 @@ class WskBasicTests extends TestHelpers with 
WskTestHelpers {
   }
 
   it should "create, and fire a trigger using a parameter file" in 
withAssetCleaner(wskprops) {
-    val name = "paramFileTrigger"
-    val file = Some(TestUtils.getTestActionFilename("argCheck.js"))
+    val ruleName = withTimestamp("r1toa1")
+    val triggerName = withTimestamp("paramFileTrigger")
+    val actionName = withTimestamp("a1")
     val argInput = Some(TestUtils.getTestActionFilename("validInput2.json"))
 
     (wp, assetHelper) =>
-      assetHelper.withCleaner(wsk.trigger, name) { (trigger, _) =>
-        trigger.create(name)
+      assetHelper.withCleaner(wsk.trigger, triggerName) { (trigger, _) =>
+        trigger.create(triggerName)
+      }
+
+      assetHelper.withCleaner(wsk.action, actionName) { (action, name) =>
+        action.create(name, defaultAction)
+      }
+
+      assetHelper.withCleaner(wsk.rule, ruleName) { (rule, name) =>
+        rule.create(name, trigger = triggerName, action = actionName)
       }
 
       val expectedOutput = JsObject("payload" -> JsString("test"))
-      val run = wsk.trigger.fire(name, parameterFile = argInput)
+      val run = wsk.trigger.fire(triggerName, parameterFile = argInput)
       withActivation(wsk.activation, run) { activation =>
         activation.response.result shouldBe Some(expectedOutput)
       }
@@ -568,12 +598,23 @@ class WskBasicTests extends TestHelpers with 
WskTestHelpers {
   }
 
   it should "create, and fire a trigger to ensure result is empty" in 
withAssetCleaner(wskprops) { (wp, assetHelper) =>
-    val name = "emptyResultTrigger"
-    assetHelper.withCleaner(wsk.trigger, name) { (trigger, _) =>
-      trigger.create(name)
+    val ruleName = withTimestamp("r1toa1")
+    val triggerName = withTimestamp("emptyResultTrigger")
+    val actionName = withTimestamp("a1")
+
+    assetHelper.withCleaner(wsk.trigger, triggerName) { (trigger, _) =>
+      trigger.create(triggerName)
+    }
+
+    assetHelper.withCleaner(wsk.action, actionName) { (action, name) =>
+      action.create(name, defaultAction)
     }
 
-    val run = wsk.trigger.fire(name)
+    assetHelper.withCleaner(wsk.rule, ruleName) { (rule, name) =>
+      rule.create(name, trigger = triggerName, action = actionName)
+    }
+
+    val run = wsk.trigger.fire(triggerName)
     withActivation(wsk.activation, run) { activation =>
       activation.response.result shouldBe Some(JsObject())
     }
@@ -785,21 +826,31 @@ class WskBasicTests extends TestHelpers with 
WskTestHelpers {
 
   it should "create a trigger, and fire a trigger to get its individual fields 
from an activation" in withAssetCleaner(
     wskprops) { (wp, assetHelper) =>
-    val name = "activationFields"
+    val ruleName = withTimestamp("r1toa1")
+    val triggerName = withTimestamp("activationFields")
+    val actionName = withTimestamp("a1")
 
-    assetHelper.withCleaner(wsk.trigger, name) { (trigger, _) =>
-      trigger.create(name)
+    assetHelper.withCleaner(wsk.trigger, triggerName) { (trigger, _) =>
+      trigger.create(triggerName)
+    }
+
+    assetHelper.withCleaner(wsk.action, actionName) { (action, name) =>
+      action.create(name, defaultAction)
+    }
+
+    assetHelper.withCleaner(wsk.rule, ruleName) { (rule, name) =>
+      rule.create(name, trigger = triggerName, action = actionName)
     }
 
     val ns = s""""${wsk.namespace.whois()}""""
-    val run = wsk.trigger.fire(name)
+    val run = wsk.trigger.fire(triggerName)
     withActivation(wsk.activation, run) { activation =>
       val successMsg = s"ok: got activation ${activation.activationId}, 
displaying field"
       wsk.activation
         .get(Some(activation.activationId), fieldFilter = Some("namespace"))
         .stdout should include regex (s"""(?i)$successMsg namespace\n$ns""")
       wsk.activation.get(Some(activation.activationId), fieldFilter = 
Some("name")).stdout should include(
-        s"""$successMsg name\n"$name"""")
+        s"""$successMsg name\n"$triggerName"""")
       wsk.activation.get(Some(activation.activationId), fieldFilter = 
Some("version")).stdout should include(
         s"""$successMsg version\n"0.0.1"""")
       wsk.activation.get(Some(activation.activationId), fieldFilter = 
Some("publish")).stdout should include(
diff --git a/tests/src/test/scala/system/basic/WskRuleTests.scala 
b/tests/src/test/scala/system/basic/WskRuleTests.scala
index 2baac6d850..bcb9dea083 100644
--- a/tests/src/test/scala/system/basic/WskRuleTests.scala
+++ b/tests/src/test/scala/system/basic/WskRuleTests.scala
@@ -100,13 +100,11 @@ abstract class WskRuleTests extends TestHelpers with 
WskTestHelpers {
 
     withActivation(wsk.activation, run) { triggerActivation =>
       triggerActivation.cause shouldBe None
-
-      withActivationsFromEntity(
-        wsk.activation,
-        ruleName,
-        since = 
Some(triggerActivation.start.minusMillis(activationTimeSkewFactorMs))) {
-        _.head.cause shouldBe Some(triggerActivation.activationId)
-      }
+      triggerActivation.logs.get.size shouldBe (1)
+      val logs = triggerActivation.logs.get.mkString(" ")
+      logs should include(""""statusCode":0""")
+      logs should include(""""activationId":""")
+      logs should include(""""success":true""")
 
       withActivationsFromEntity(
         wsk.activation,
@@ -137,13 +135,11 @@ abstract class WskRuleTests extends TestHelpers with 
WskTestHelpers {
 
     withActivation(wsk.activation, run) { triggerActivation =>
       triggerActivation.cause shouldBe None
-
-      withActivationsFromEntity(
-        wsk.activation,
-        ruleName,
-        since = 
Some(triggerActivation.start.minusMillis(activationTimeSkewFactorMs))) {
-        _.head.cause shouldBe Some(triggerActivation.activationId)
-      }
+      triggerActivation.logs.get.size shouldBe (1)
+      val logs = triggerActivation.logs.get.mkString(" ")
+      logs should include(""""statusCode":0""")
+      logs should include(""""activationId":""")
+      logs should include(""""success":true""")
 
       withActivationsFromEntity(
         wsk.activation,
@@ -177,13 +173,11 @@ abstract class WskRuleTests extends TestHelpers with 
WskTestHelpers {
 
     withActivation(wsk.activation, run) { triggerActivation =>
       triggerActivation.cause shouldBe None
-
-      withActivationsFromEntity(
-        wsk.activation,
-        ruleName,
-        since = 
Some(triggerActivation.start.minusMillis(activationTimeSkewFactorMs))) {
-        _.head.cause shouldBe Some(triggerActivation.activationId)
-      }
+      triggerActivation.logs.get.size shouldBe (1)
+      val logs = triggerActivation.logs.get.mkString(" ")
+      logs should include(""""statusCode":0""")
+      logs should include(""""activationId":""")
+      logs should include(""""success":true""")
 
       withActivationsFromEntity(
         wsk.activation,
diff --git a/tests/src/test/scala/whisk/core/cli/test/Swift311Tests.scala 
b/tests/src/test/scala/whisk/core/cli/test/Swift311Tests.scala
index a00b1ea6e4..1dc19f0cfb 100644
--- a/tests/src/test/scala/whisk/core/cli/test/Swift311Tests.scala
+++ b/tests/src/test/scala/whisk/core/cli/test/Swift311Tests.scala
@@ -37,6 +37,7 @@ class Swift311Tests extends TestHelpers with WskTestHelpers 
with Matchers {
   val wsk = new WskRest
   val expectedDuration = 45 seconds
   val activationPollDuration = 60 seconds
+  val defaultJsAction = Some(TestUtils.getTestActionFilename("hello.js"))
 
   lazy val runtimeContainer = "swift:3.1.1"
 
@@ -116,10 +117,20 @@ class Swift311Tests extends TestHelpers with 
WskTestHelpers with Matchers {
   it should "allow Swift actions to trigger events" in 
withAssetCleaner(wskprops) { (wp, assetHelper) =>
     // create a trigger
     val triggerName = s"TestTrigger ${System.currentTimeMillis()}"
+    val ruleName = s"TestTriggerRule ${System.currentTimeMillis()}"
+    val ruleActionName = s"TestTriggerAction ${System.currentTimeMillis()}"
     assetHelper.withCleaner(wsk.trigger, triggerName) { (trigger, _) =>
       trigger.create(triggerName)
     }
 
+    assetHelper.withCleaner(wsk.action, ruleActionName) { (action, name) =>
+      action.create(name, defaultJsAction)
+    }
+
+    assetHelper.withCleaner(wsk.rule, ruleName) { (rule, name) =>
+      rule.create(name, trigger = triggerName, action = ruleActionName)
+    }
+
     // create an action that fires the trigger
     val file = TestUtils.getTestActionFilename("trigger.swift")
     val actionName = "ActionThatTriggers"
diff --git 
a/tests/src/test/scala/whisk/core/controller/test/TriggersApiTests.scala 
b/tests/src/test/scala/whisk/core/controller/test/TriggersApiTests.scala
index 200086f6da..3a8d3cee4f 100644
--- a/tests/src/test/scala/whisk/core/controller/test/TriggersApiTests.scala
+++ b/tests/src/test/scala/whisk/core/controller/test/TriggersApiTests.scala
@@ -64,6 +64,7 @@ class TriggersApiTests extends ControllerTestCommon with 
WhiskTriggersApi {
   val namespace = EntityPath(creds.subject.asString)
   val collectionPath = s"/${EntityPath.DEFAULT}/${collection.path}"
   def aname() = MakeName.next("triggers_tests")
+  def afullname(namespace: EntityPath, name: String) = 
FullyQualifiedEntityName(namespace, EntityName(name))
   val parametersLimit = Parameters.sizeLimit
 
   //// GET /triggers
@@ -319,9 +320,13 @@ class TriggersApiTests extends ControllerTestCommon with 
WhiskTriggersApi {
   //// POST /triggers/name
   it should "fire a trigger" in {
     implicit val tid = transid()
-    val trigger = WhiskTrigger(namespace, aname(), Parameters("x", "b"))
+    val rule = WhiskRule(namespace, aname(), afullname(namespace, 
aname().name), afullname(namespace, "bogus action"))
+    val trigger = WhiskTrigger(namespace, rule.trigger.name, rules = Some {
+      Map(rule.fullyQualifiedName(false) -> ReducedRule(rule.action, 
Status.ACTIVE))
+    })
     val content = JsObject("xxx" -> "yyy".toJson)
     put(entityStore, trigger)
+    put(entityStore, rule)
     Post(s"$collectionPath/${trigger.name}", content) ~> 
Route.seal(routes(creds)) ~> check {
       status should be(Accepted)
       val response = responseAs[JsObject]
@@ -342,8 +347,12 @@ class TriggersApiTests extends ControllerTestCommon with 
WhiskTriggersApi {
 
   it should "fire a trigger without args" in {
     implicit val tid = transid()
-    val trigger = WhiskTrigger(namespace, aname(), Parameters("x", "b"))
+    val rule = WhiskRule(namespace, aname(), afullname(namespace, 
aname().name), afullname(namespace, "bogus action"))
+    val trigger = WhiskTrigger(namespace, rule.trigger.name, Parameters("x", 
"b"), rules = Some {
+      Map(rule.fullyQualifiedName(false) -> ReducedRule(rule.action, 
Status.ACTIVE))
+    })
     put(entityStore, trigger)
+    put(entityStore, rule)
     Post(s"$collectionPath/${trigger.name}") ~> Route.seal(routes(creds)) ~> 
check {
       val response = responseAs[JsObject]
       val JsString(id) = response.fields("activationId")


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
[email protected]


With regards,
Apache Git Services

Reply via email to