Netowrk Bootstrapper CLI enhancements (#3634)

This commit is contained in:
Stefano Franz 2018-07-18 15:26:49 +01:00 committed by Katelyn Baker
parent baeb72366c
commit 8585ade599
7 changed files with 26 additions and 25 deletions

View File

@ -1,4 +1,5 @@
@file:JvmName("Main")
package net.corda.bootstrapper
import javafx.application.Application
@ -15,7 +16,13 @@ val baseArgs = CliParser()
fun main(args: Array<String>) {
SerializationEngine.init()
CommandLine(baseArgs).parse(*args)
val commandLine = CommandLine(baseArgs)
commandLine.parse(*args)
if (commandLine.isUsageHelpRequested) {
commandLine.usage(System.out)
return
}
if (baseArgs.gui) {
Application.launch(Gui::class.java)

View File

@ -7,7 +7,6 @@ import net.corda.bootstrapper.notaries.NotaryCopier
import net.corda.bootstrapper.notaries.NotaryFinder
import java.io.File
import java.util.concurrent.CompletableFuture
import java.util.concurrent.ConcurrentHashMap
interface NetworkBuilder {
@ -23,7 +22,6 @@ interface NetworkBuilder {
fun onNodePushed(callback: (PushedNode) -> Unit): NetworkBuilder
fun onNodeInstance(callback: (NodeInstance) -> Unit): NetworkBuilder
fun withNodeCounts(map: Map<String, Int>): NetworkBuilder
fun withNetworkName(networtName: String): NetworkBuilder
fun withBasedir(baseDir: File): NetworkBuilder
fun withBackend(backendType: Backend.BackendType): NetworkBuilder
@ -104,11 +102,6 @@ private class NetworkBuilderImpl : NetworkBuilder {
return this
}
override fun withNodeCounts(map: Map<String, Int>): NetworkBuilder {
nodeCounts = ConcurrentHashMap(map.entries.map { it.key.toLowerCase() to it.value }.toMap())
return this
}
override fun withNetworkName(networtName: String): NetworkBuilder {
this.networkName = networtName
return this

View File

@ -9,6 +9,7 @@ import net.corda.bootstrapper.nodes.NodeAdder
import net.corda.bootstrapper.nodes.NodeInstantiator
import net.corda.bootstrapper.toSingleFuture
import net.corda.bootstrapper.useAndClose
import net.corda.core.identity.CordaX500Name
import net.corda.core.utilities.getOrThrow
import java.io.File
@ -25,7 +26,6 @@ class CommandLineInterface {
val (_, context) = NetworkBuilder.instance()
.withBasedir(baseDir)
.withNetworkName(networkName)
.withNodeCounts(parsedArgs.nodes)
.onNodeBuild { builtNode -> println("Built node: ${builtNode.name} to image: ${builtNode.localImageId}") }
.onNodePushed { pushedNode -> println("Pushed node: ${pushedNode.name} to: ${pushedNode.remoteImageName}") }
.onNodeInstance { instance ->
@ -42,7 +42,7 @@ class CommandLineInterface {
val (_, instantiator, _) = Backend.fromContext(context, cacheDir)
val nodeAdder = NodeAdder(context, NodeInstantiator(instantiator, context))
parsedArgs.nodesToAdd.map {
nodeAdder.addNode(context, Constants.ALPHA_NUMERIC_ONLY_REGEX.replace(it.toLowerCase(), ""))
nodeAdder.addNode(context, Constants.ALPHA_NUMERIC_ONLY_REGEX.replace(it.key.toLowerCase(), ""), CordaX500Name.parse(it.value))
}.toSingleFuture().getOrThrow()
persistContext(contextFile, objectMapper, context)
}

View File

@ -8,6 +8,7 @@ import picocli.CommandLine.Option
import java.io.File
open class CliParser {
@Option(names = arrayOf("-n", "--network-name"), description = arrayOf("The resource grouping to use"))
var name: String? = null
@ -20,11 +21,11 @@ open class CliParser {
@Option(names = arrayOf("-b", "--backend"), description = arrayOf("The backend to use when instantiating nodes"))
var backendType: Backend.BackendType = Backend.BackendType.LOCAL_DOCKER
@Option(names = arrayOf("--nodes"), split = ":", description = arrayOf("The number of each node to create. NodeX:2 will create two instances of NodeX"))
var nodes: MutableMap<String, Int> = hashMapOf()
@Option(names = arrayOf("--add"), split = ":", description = arrayOf("The node to add. Format is <Name>:<X500>. Eg; \"Node1:O=Bank A, L=New York, C=US, OU=Org Unit, CN=Service Name\""))
var nodesToAdd: MutableMap<String, String> = hashMapOf()
@Option(names = arrayOf("--add", "-a"))
var nodesToAdd: MutableList<String> = arrayListOf()
@Option(names = arrayOf("-h", "--help"), usageHelp = true, description = arrayOf("display a help message"))
var helpRequested = false
fun isNew(): Boolean {
return nodesToAdd.isEmpty()

View File

@ -20,6 +20,7 @@ import net.corda.bootstrapper.backends.Backend
import net.corda.bootstrapper.context.Context
import net.corda.bootstrapper.nodes.*
import net.corda.bootstrapper.notaries.NotaryFinder
import net.corda.core.identity.CordaX500Name
import org.apache.commons.lang3.RandomStringUtils
import org.controlsfx.control.SegmentedButton
import tornadofx.*
@ -69,7 +70,6 @@ class BootstrapperView : View("Corda Network Builder") {
}
}
val nodeCount = controller.foundNodes.map { it.id to it.count }.toMap()
val result = NetworkBuilder.instance()
.withBasedir(controller.baseDir.get())
.withNetworkName(networkName)
@ -80,7 +80,6 @@ class BootstrapperView : View("Corda Network Builder") {
.onNodeInstancesRequested(controller::addInstanceRequests)
.onNodeInstance(controller::addInstance)
.withBackend(selectedBackEnd)
.withNodeCounts(nodeCount)
.withBackendOptions(backendParams)
.build()
@ -117,6 +116,10 @@ class BootstrapperView : View("Corda Network Builder") {
enableWhen { controller.networkContext.isNotNull }
action {
templateChoiceBox.selectionModel.selectedItem?.let { nodeToAdd ->
val textInputDialog = TextInputDialog("O=Bank A, L=New York, C=US, OU=Org Unit, CN=Service Name")
textInputDialog.title = "X500 of node to add"
val x500ToUse = textInputDialog.showAndWait().orElseGet { null }
val context = controller.networkContext.value
runLater {
val (_, instantiator, _) = Backend.fromContext(
@ -124,7 +127,7 @@ class BootstrapperView : View("Corda Network Builder") {
File(controller.baseDir.get(), Constants.BOOTSTRAPPER_DIR_NAME))
val nodeAdder = NodeAdder(context, NodeInstantiator(instantiator, context))
controller.addInstanceRequest(nodeToAdd)
nodeAdder.addNode(context, nodeToAdd).handleAsync { instanceInfo, t ->
nodeAdder.addNode(context, nodeToAdd, x500ToUse?.let { CordaX500Name.parse(it) }).handleAsync { instanceInfo, t ->
t?.let {
GuiUtils.showException("Failed", "Failed to add node", it)
}
@ -256,10 +259,6 @@ class BootstrapperView : View("Corda Network Builder") {
compareValues(o1.nodeType.toString() + o1.templateId, o2.nodeType.toString() + o2.templateId) * -1
})
fun clear() {
networkContext.set(null)
}
fun clearAll() {
networkContext.set(null)
foundNodes.clear()

View File

@ -2,17 +2,18 @@ package net.corda.bootstrapper.nodes
import net.corda.bootstrapper.containers.instance.InstanceInfo
import net.corda.bootstrapper.context.Context
import net.corda.core.identity.CordaX500Name
import java.util.concurrent.CompletableFuture
class NodeAdder(val context: Context,
val nodeInstantiator: NodeInstantiator) {
fun addNode(context: Context, nodeGroupName: String): CompletableFuture<InstanceInfo> {
fun addNode(context: Context, nodeGroupName: String, x500ToAdd: CordaX500Name?): CompletableFuture<InstanceInfo> {
return synchronized(context) {
val nodeGroup = context.nodes[nodeGroupName]!!
val nodeInfo = nodeGroup.iterator().next()
val currentNodeSize = nodeGroup.size
val newInstanceX500 = nodeInfo.groupX500!!.copy(commonName = nodeInfo.groupX500.commonName + (currentNodeSize)).toString()
val newInstanceX500 = x500ToAdd?.toString() ?: nodeInfo.groupX500!!.copy(commonName = nodeInfo.groupX500.commonName + (currentNodeSize)).toString()
val newInstanceName = nodeGroupName + (currentNodeSize)
val nextNodeInfo = nodeInfo.copy(
instanceX500 = newInstanceX500,

View File

@ -21,10 +21,10 @@ open class NodeBuilder {
val copiedNodeConfig = copiedNode.copiedNodeConfig
val nodeDir = copiedNodeConfig.parentFile
if (!copiedNodeConfig.exists()) {
throw IllegalStateException("There is no nodeConfig for dir: " + copiedNodeConfig)
throw IllegalStateException("There is no nodeConfig for dir: $copiedNodeConfig")
}
val nodeConfig = ConfigFactory.parseFile(copiedNodeConfig)
LOG.info("starting to build docker image for: " + nodeDir)
LOG.info("starting to build docker image for: $nodeDir")
val nodeImageId = localDockerClient.buildImageCmd()
.withDockerfile(File(nodeDir, "Dockerfile"))
.withBaseDirectory(nodeDir)