Add a command to list the triggers in a DAR (#3268)

For now, this uses a somewhat adhoc format with one trigger identifier
per line but given that I expect that it won’t be particularly common
to want to do this mechanically this should be sufficient and it’s
trivial to parse.
This commit is contained in:
Moritz Kiefer 2019-10-28 18:34:19 -04:00 committed by mergify[bot]
parent 5fbc9a20aa
commit e70bb007be
4 changed files with 114 additions and 7 deletions

View File

@ -10,6 +10,8 @@ import com.digitalasset.platform.services.time.TimeProviderType
case class RunnerConfig(
darPath: File,
// If true, we will only list the triggers in the DAR and exit.
listTriggers: Boolean,
triggerIdentifier: String,
ledgerHost: String,
ledgerPort: Int,
@ -28,22 +30,18 @@ object RunnerConfig {
.text("Path to the dar file containing the trigger")
opt[String]("trigger-name")
.required()
.action((t, c) => c.copy(triggerIdentifier = t))
.text("Identifier of the trigger that should be run in the format Module.Name:Entity.Name")
opt[String]("ledger-host")
.required()
.action((t, c) => c.copy(ledgerHost = t))
.text("Ledger hostname")
opt[Int]("ledger-port")
.required()
.action((t, c) => c.copy(ledgerPort = t))
.text("Ledger port")
opt[String]("ledger-party")
.required()
.action((t, c) => c.copy(ledgerParty = t))
.text("Ledger party")
@ -58,16 +56,41 @@ object RunnerConfig {
c.copy(commandTtl = Duration.ofSeconds(t))
}
.text("TTL in seconds used for commands emitted by the trigger. Defaults to 30s.")
cmd("list")
.action((_, c) => c.copy(listTriggers = true))
.text("List the triggers in the DAR.")
checkConfig(c =>
if (c.listTriggers) {
// I do not want to break the trigger CLI and require a
// "run" command so I cant make these options required
// in general. Therefore, we do this check in checkConfig.
success
} else {
if (c.triggerIdentifier == null) {
failure("Missing option --trigger-name")
} else if (c.ledgerHost == null) {
failure("Missing option --ledger-host")
} else if (c.ledgerPort == 0) {
failure("Missing option --ledger-port")
} else if (c.ledgerParty == null) {
failure("Missing option --ledger-pary")
} else {
success
}
})
}
def parse(args: Array[String]): Option[RunnerConfig] =
parser.parse(
args,
RunnerConfig(
darPath = null,
listTriggers = false,
triggerIdentifier = null,
ledgerHost = "",
ledgerHost = null,
ledgerPort = 0,
ledgerParty = "",
ledgerParty = null,
timeProviderType = TimeProviderType.Static,
commandTtl = Duration.ofSeconds(30L),
)

View File

@ -5,6 +5,7 @@ package com.daml.trigger
import akka.actor.ActorSystem
import akka.stream._
import java.io.File
import scala.concurrent.{Await, ExecutionContext, Future}
import scala.concurrent.duration.Duration
import scalaz.syntax.traverse._
@ -12,7 +13,7 @@ import scalaz.syntax.traverse._
import com.digitalasset.daml.lf.archive.{Dar, DarReader}
import com.digitalasset.daml.lf.archive.Decode
import com.digitalasset.daml.lf.data.Ref.{Identifier, PackageId, QualifiedName}
import com.digitalasset.daml.lf.language.Ast.Package
import com.digitalasset.daml.lf.language.Ast._
import com.digitalasset.daml_lf_dev.DamlLf
import com.digitalasset.grpc.adapter.AkkaExecutionSequencerPool
import com.digitalasset.ledger.api.refinements.ApiTypes.ApplicationId
@ -25,6 +26,24 @@ import com.digitalasset.ledger.client.configuration.{
object RunnerMain {
def listTriggers(darPath: File, dar: Dar[(PackageId, Package)]) = {
val triggerIds = TriggerIds.fromDar(dar)
println(s"Listing triggers in $darPath:")
for ((modName, mod) <- dar.main._2.modules) {
for ((defName, defVal) <- mod.definitions) {
defVal match {
case DValue(TApp(TTyCon(tcon), _), _, _, _) => {
if (tcon == triggerIds.getHighlevelId("Trigger")
|| tcon == triggerIds.getId("Trigger")) {
println(s" $modName:$defName")
}
}
case _ => {}
}
}
}
}
def main(args: Array[String]): Unit = {
RunnerConfig.parse(args) match {
@ -36,6 +55,11 @@ object RunnerMain {
case (pkgId, pkgArchive) => Decode.readArchivePayload(pkgId, pkgArchive)
}
if (config.listTriggers) {
listTriggers(config.darPath, dar)
sys.exit(0)
}
val triggerId: Identifier =
Identifier(dar.main._1, QualifiedName.assertFromString(config.triggerIdentifier))

View File

@ -88,3 +88,19 @@ client_server_test(
],
server_files = ["$(rootpath :acs.dar)"],
)
sh_test(
name = "list-triggers",
srcs = ["list-triggers.sh"],
args = [
"$(location //triggers/runner:trigger-runner)",
"$(location :acs.dar)",
],
data = [
":acs.dar",
"//triggers/runner:trigger-runner",
],
deps = [
"@bazel_tools//tools/bash/runfiles",
],
)

44
triggers/tests/list-triggers.sh Executable file
View File

@ -0,0 +1,44 @@
# Copyright (c) 2019 The DAML Authors. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
set -eou pipefail
# --- begin runfiles.bash initialization ---
# Copy-pasted from Bazel's Bash runfiles library (tools/bash/runfiles/runfiles.bash).
if [[ ! -d "${RUNFILES_DIR:-/dev/null}" && ! -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then
if [[ -f "$0.runfiles_manifest" ]]; then
export RUNFILES_MANIFEST_FILE="$0.runfiles_manifest"
elif [[ -f "$0.runfiles/MANIFEST" ]]; then
export RUNFILES_MANIFEST_FILE="$0.runfiles/MANIFEST"
elif [[ -f "$0.runfiles/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then
export RUNFILES_DIR="$0.runfiles"
fi
fi
if [[ -f "${RUNFILES_DIR:-/dev/null}/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then
source "${RUNFILES_DIR}/bazel_tools/tools/bash/runfiles/runfiles.bash"
elif [[ -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then
source "$(grep -m1 "^bazel_tools/tools/bash/runfiles/runfiles.bash " \
"$RUNFILES_MANIFEST_FILE" | cut -d ' ' -f 2-)"
else
echo >&2 "ERROR: cannot find @bazel_tools//tools/bash/runfiles:runfiles.bash"
exit 1
fi
# --- end runfiles.bash initialization ---
TRIGGER_EXE=$(rlocation "$TEST_WORKSPACE/$1")
DAR=$(rlocation "$TEST_WORKSPACE/$2")
OUTPUT="$($TRIGGER_EXE list --dar $DAR | tail -n '+2' | tr -d '\r')"
EXPECTED="\
Retry:retryTrigger
ACS:test
CopyTrigger:copyTrigger\
"
if [ "$OUTPUT" != "$EXPECTED" ]; then
echo "Unexpected output:"
echo "$OUTPUT"
echo "Expected:"
echo "$EXPECTED"
exit 1
fi