Skip to content
This repository was archived by the owner on Nov 22, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -248,3 +248,23 @@ You can explicitly verify if the blueprint connects all the streamlets correctly
----

The blueprint is automatically verified when you use application-level targets, like `buildApp` and `runLocal`.

You can visualize your blueprint as a graph by using:

[source,bash]
----
sbt printAppGraph
----

This task will print an ASCII graph to the console.

Or use:

[source,bash]
----
sbt saveAppGraph
----

Which will save an ASCII graph to the `appGraph.txt` file under the `target/visuals/blueprint` folder of your Cloudflow project.

You can also override the `appGraphSavePath` setting key to provide a new path for the App Graph file to save.
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,6 @@ object CloudflowApplicationPlugin extends AutoPlugin {
packageOptions in (Compile, packageBin) +=
Package.ManifestAttributes(new java.util.jar.Attributes.Name("Blueprint") -> blueprintFile.value.getName),
verifyBlueprint := verifyBlueprint.value,
buildApp := cloudflowApplicationCR.value)
buildApp := cloudflowApplicationCR.value,
appGraphSavePath := target.value / "visuals" / "blueprint")
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ trait CloudflowSettingKeys {
val initialDebugPort =
settingKey[Int]("Initial port number for debugging in runLocal. It will be increased by one for each Streamlet")
val remoteDebugRunLocal = settingKey[Boolean]("Enable/Disable remote debugging for streamlets in runLocal")
val appGraphSavePath = settingKey[File]("The path where an application graph visualization should be saved.")
}

trait CloudflowTaskKeys {
Expand All @@ -82,6 +83,7 @@ trait CloudflowTaskKeys {
val extraDockerInstructions = taskKey[Seq[sbtdocker.Instruction]]("A list of instructions to add to the dockerfile.")
val verifyBlueprint = taskKey[Unit]("Verify Blueprint.")
val printAppGraph = taskKey[Unit]("Print graph of all streamlets and how they are connected.")
val saveAppGraph = taskKey[File]("Save graph of all streamlets and how they are connected as a text file.")
val build = taskKey[Unit]("Build the image.")
val buildAndPublish = taskKey[Unit]("[Deprecated! Use buildApp] Build and publish the image.")
val runLocal = taskKey[Unit]("Run the Cloudflow application in a local Sandbox.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ object CloudflowLocalRunnerPlugin extends AutoPlugin {
host
}

printAppLayout(resolveConnections(appDescriptor))
println(getAppLayout(resolveConnections(appDescriptor)))
printInfo(runtimeDescriptorByProject, tempDir.toFile, topics, localConfig.message)

val processes = runtimeDescriptorByProject.zipWithIndex.map {
Expand Down Expand Up @@ -177,7 +177,8 @@ object CloudflowLocalRunnerPlugin extends AutoPlugin {
}
}
}.value,
printAppGraph := printApplicationGraph.value)
printAppGraph := printApplicationGraph.value,
saveAppGraph := saveApplicationGraph.value)

def banner(bannerChar: Char)(name: String)(message: Any): Unit = {
val title = s" $name "
Expand Down Expand Up @@ -310,7 +311,22 @@ object CloudflowLocalRunnerPlugin extends AutoPlugin {
logger.error("LocalRunner: ApplicationDescriptor is not present. This is a bug. Please report it.")
throw new IllegalStateException("ApplicationDescriptor is not present")
}
printAppLayout(resolveConnections(appDescriptor))
println(getAppLayout(resolveConnections(appDescriptor)))
}

def saveApplicationGraph: Def.Initialize[Task[File]] = Def.task {
implicit val logger = streams.value.log
val _appDescriptor = applicationDescriptor.value
val appGraphDir = appGraphSavePath.value
val appGraphFile = appGraphDir / "appGraph.txt"
val appDescriptor = _appDescriptor.getOrElse {
logger.error("LocalRunner: ApplicationDescriptor is not present. This is a bug. Please report it.")
throw new IllegalStateException("ApplicationDescriptor is not present")
}
val layoutGraph = getAppLayout(resolveConnections(appDescriptor))
IO.write(appGraphFile, layoutGraph)
logger.info(s"App graph file is generated: $appGraphFile")
appGraphFile
}

def resolveConnections(appDescriptor: ApplicationDescriptor): List[(String, String)] = {
Expand Down Expand Up @@ -342,12 +358,19 @@ object CloudflowLocalRunnerPlugin extends AutoPlugin {
}.toList
}

@deprecated("Use 'getAppLayout' instead")
def printAppLayout(connections: List[(String, String)]): Unit = {
val vertices = connections.flatMap { case (a, b) => Seq(a, b) }.toSet
val graph = Graph(vertices = vertices, edges = connections)
println(GraphLayout.renderGraph(graph))
}

def getAppLayout(connections: List[(String, String)]): String = {
Comment thread
Lockdain marked this conversation as resolved.
val vertices = connections.flatMap { case (a, b) => Seq(a, b) }.toSet
val graph = Graph(vertices = vertices, edges = connections)
GraphLayout.renderGraph(graph)
}

def scaffoldRuntime(
projectId: String,
descriptor: ApplicationDescriptor,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
lazy val helloWorld = (project in file("."))
.enablePlugins(CloudflowApplicationPlugin, CloudflowAkkaPlugin)
.settings(
scalaVersion := "2.12.11",
name := "hello-world",
version := "0.0.1",
cloudflowDockerBaseImage := "adoptopenjdk/openjdk11:alpine",
libraryDependencies ++= Seq(
"ch.qos.logback" % "logback-classic" % "1.2.3"
)
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
sys.props.get("plugin.version") match {
case Some(x) => addSbtPlugin("com.lightbend.cloudflow" % "sbt-cloudflow" % x)
case _ => sys.error("""|The system property 'plugin.version' is not defined.
|Specify this property using the scriptedLaunchOpts -D.""".stripMargin)
}

libraryDependencies += "com.lihaoyi" %% "ujson" % "0.9.5"
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
blueprint {
streamlets {
hello-world = helloworld.HelloWorldShape
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (C) 2016-2021 Lightbend Inc. <https://www.lightbend.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package helloworld

import akka.stream.scaladsl._
import cloudflow.akkastream._
import cloudflow.akkastream.scaladsl._
import cloudflow.streamlets._

class HelloWorldShape extends AkkaStreamlet {
val shape = StreamletShape.empty

def createLogic = new RunnableGraphStreamletLogic() {
def runnableGraph =
Source
.single("Hello, world!")
.map(println)
.to(Sink.ignore)
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# save an app graph file to the default path
> saveAppGraph
$ exists target/visuals/blueprint/appGraph.txt

# print an app graph to the console
> printAppGraph