in common/scala/src/main/scala/org/apache/openwhisk/core/entity/Exec.scala [282:355]
override def read(v: JsValue) = {
require(v != null)
val obj = v.asJsObject
val kind = obj.fields.get("kind") match {
case Some(JsString(k)) => k.trim.toLowerCase
case _ => throw new DeserializationException("'kind' must be a string defined in 'exec'")
}
lazy val optMainField: Option[String] = obj.fields.get("main") match {
case Some(JsString(m)) => Some(m)
case Some(_) =>
throw new DeserializationException(s"if defined, 'main' be a string in 'exec' for '$kind' actions")
case None => None
}
kind match {
case Exec.SEQUENCE =>
val comp: Vector[FullyQualifiedEntityName] = obj.fields.get("components") match {
case Some(JsArray(components)) => components map (FullyQualifiedEntityName.serdes.read(_))
case Some(_) => throw new DeserializationException(s"'components' must be an array")
case None => throw new DeserializationException(s"'components' must be defined for sequence kind")
}
SequenceExec(comp)
case Exec.BLACKBOX =>
val image: ImageName = obj.fields.get("image") match {
case Some(JsString(i)) => ImageName.fromString(i).get // throws deserialization exception on failure
case _ =>
throw new DeserializationException(
s"'image' must be a string defined in 'exec' for '${Exec.BLACKBOX}' actions")
}
val (codeOpt: Option[Attachment[String]], binary) = obj.fields.get("code") match {
case None => (None, false)
case Some(JsString(i)) if i.trim.isEmpty => (None, false)
case Some(code) => (Some(attFmt[String].read(code)), isBinary(code, obj))
}
val native = execManifests.skipDockerPull(image)
BlackBoxExec(image, codeOpt, optMainField, native, binary)
case _ =>
// map "default" virtual runtime versions to the currently blessed actual runtime version
val manifest = execManifests.resolveDefaultRuntime(kind) match {
case Some(k) => k
case None => throw new DeserializationException(Messages.invalidRuntimeError(kind, runtimes))
}
manifest.attached
.map { _ =>
// java actions once stored the attachment in "jar" instead of "code"
val code = obj.fields.get("code").orElse(obj.fields.get("jar")).getOrElse {
throw new DeserializationException(
s"'code' must be a string or attachment object defined in 'exec' for '$kind' actions")
}
val main = optMainField.orElse {
if (manifest.requireMain.exists(identity)) {
throw new DeserializationException(s"'main' must be a string defined in 'exec' for '$kind' actions")
} else None
}
CodeExecAsAttachment(manifest, attFmt[String].read(code), main, isBinary(code, obj))
}
.getOrElse {
val code: String = obj.fields.get("code") match {
case Some(JsString(c)) => c
case _ =>
throw new DeserializationException(s"'code' must be a string defined in 'exec' for '$kind' actions")
}
CodeExecAsString(manifest, code, optMainField)
}
}
}