/* * Copyright 2013-2015 the original author or authors. * * 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 org.springframework.xd.shell.command; import static org.springframework.xd.shell.command.DeploymentOptionKeys.PROPERTIES_FILE_OPTION; import static org.springframework.xd.shell.command.DeploymentOptionKeys.PROPERTIES_OPTION; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.Collections; import java.util.Map; import java.util.Properties; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.hateoas.PagedResources; import org.springframework.shell.core.CommandMarker; import org.springframework.shell.core.annotation.CliAvailabilityIndicator; import org.springframework.shell.core.annotation.CliCommand; import org.springframework.shell.core.annotation.CliOption; import org.springframework.stereotype.Component; import org.springframework.xd.rest.client.StreamOperations; import org.springframework.xd.rest.domain.StreamDefinitionResource; import org.springframework.xd.rest.domain.support.DeploymentPropertiesFormat; import org.springframework.xd.shell.XDShell; import org.springframework.xd.shell.util.Assertions; import org.springframework.xd.shell.util.Table; import org.springframework.xd.shell.util.TableHeader; @Component public class StreamCommands implements CommandMarker { private static final String CREATE_STREAM = "stream create"; private static final String LIST_STREAM = "stream list"; private static final String DEPLOY_STREAM = "stream deploy"; private static final String UNDEPLOY_STREAM = "stream undeploy"; private static final String UNDEPLOY_STREAM_ALL = "stream all undeploy"; private static final String DESTROY_STREAM = "stream destroy"; private static final String DESTROY_STREAM_ALL = "stream all destroy"; @Autowired private UserInput userInput; @Autowired private XDShell xdShell; @CliAvailabilityIndicator({ CREATE_STREAM, LIST_STREAM, DEPLOY_STREAM, UNDEPLOY_STREAM, DESTROY_STREAM, DESTROY_STREAM_ALL, UNDEPLOY_STREAM_ALL }) public boolean available() { return xdShell.getSpringXDOperations() != null; } @CliCommand(value = CREATE_STREAM, help = "Create a new stream definition") public String createStream( @CliOption(mandatory = true, key = { "", "name" }, help = "the name to give to the stream") String name, @CliOption(mandatory = true, key = { "definition" }, optionContext = "completion-stream disable-string-converter", help = "a stream definition, using XD DSL (e.g. \"http --port=9000 | hdfs\")") String dsl, @CliOption(key = "deploy", help = "whether to deploy the stream immediately", unspecifiedDefaultValue = "false", specifiedDefaultValue = "true") boolean deploy) { streamOperations().createStream(name, dsl, deploy); return (deploy) ? String.format("Created and deployed new stream '%s'", name) : String.format( "Created new stream '%s'", name); } @CliCommand(value = DESTROY_STREAM, help = "Destroy an existing stream") public String destroyStream( @CliOption(key = { "", "name" }, help = "the name of the stream to destroy", mandatory = true, optionContext = "existing-stream disable-string-converter") String name) { streamOperations().destroy(name); return String.format("Destroyed stream '%s'", name); } @CliCommand(value = DESTROY_STREAM_ALL, help = "Destroy all existing streams") public String destroyAllStreams( @CliOption(key = "force", help = "bypass confirmation prompt", unspecifiedDefaultValue = "false", specifiedDefaultValue = "true") boolean force) { // Be sure to short-circuit prompt if force is true if (force || "y".equalsIgnoreCase(userInput.promptWithOptions("Really destroy all streams?", "n", "y", "n"))) { streamOperations().destroyAll(); return "Destroyed all streams"; } else { return ""; } } @CliCommand(value = DEPLOY_STREAM, help = "Deploy a previously created stream") public String deployStream( @CliOption(key = { "", "name" }, help = "the name of the stream to deploy", mandatory = true, optionContext = "existing-stream undeployed disable-string-converter") String name, @CliOption(key = { PROPERTIES_OPTION }, help = "the properties for this deployment", mandatory = false) String properties, @CliOption(key = { PROPERTIES_FILE_OPTION }, help = "the properties for this deployment (as a File)", mandatory = false) File propertiesFile ) throws IOException { int which = Assertions.atMostOneOf(PROPERTIES_OPTION, properties, PROPERTIES_FILE_OPTION, propertiesFile); Map<String, String> propertiesToUse; switch (which) { case 0: propertiesToUse = DeploymentPropertiesFormat.parseDeploymentProperties(properties); break; case 1: Properties props = new Properties(); try (FileInputStream fis = new FileInputStream(propertiesFile)) { props.load(fis); } propertiesToUse = DeploymentPropertiesFormat.convert(props); break; case -1: // Neither option specified propertiesToUse = Collections.<String, String> emptyMap(); break; default: throw new AssertionError(); } streamOperations().deploy(name, propertiesToUse); return String.format("Deployed stream '%s'", name); } @CliCommand(value = UNDEPLOY_STREAM, help = "Un-deploy a previously deployed stream") public String undeployStream( @CliOption(key = { "", "name" }, help = "the name of the stream to un-deploy", mandatory = true, optionContext = "existing-stream deployed disable-string-converter") String name ) { streamOperations().undeploy(name); return String.format("Un-deployed stream '%s'", name); } @CliCommand(value = UNDEPLOY_STREAM_ALL, help = "Un-deploy all previously deployed stream") public String undeployAllStreams( @CliOption(key = "force", help = "bypass confirmation prompt", unspecifiedDefaultValue = "false", specifiedDefaultValue = "true") boolean force ) { if (force || "y".equalsIgnoreCase(userInput.promptWithOptions("Really undeploy all streams?", "n", "y", "n"))) { streamOperations().undeployAll(); return String.format("Un-deployed all the streams"); } else { return ""; } } @CliCommand(value = LIST_STREAM, help = "List created streams") public Table listStreams() { final PagedResources<StreamDefinitionResource> streams = streamOperations().list(); final Table table = new Table() .addHeader(1, new TableHeader("Stream Name")) .addHeader(2, new TableHeader("Stream Definition")) .addHeader(3, new TableHeader("Status")); for (StreamDefinitionResource stream : streams) { table.newRow() .addValue(1, stream.getName()) .addValue(2, stream.getDefinition()) .addValue(3, stream.getStatus()); } return table; } /*default*/ StreamOperations streamOperations() { return xdShell.getSpringXDOperations().streamOperations(); } }