Java tutorial
/* * Copyright 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.cloud.dataflow.shell.command; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; import java.util.Properties; import org.apache.commons.io.FilenameUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.YamlPropertiesFactoryBean; import org.springframework.boot.env.YamlPropertySourceLoader; import org.springframework.cloud.dataflow.rest.client.DataFlowOperations; import org.springframework.cloud.dataflow.rest.client.StreamOperations; import org.springframework.cloud.dataflow.rest.resource.StreamDefinitionResource; import org.springframework.cloud.dataflow.rest.util.DeploymentPropertiesUtils; import org.springframework.cloud.dataflow.shell.config.DataFlowShell; import org.springframework.core.io.FileSystemResource; 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.shell.table.BeanListTableModel; import org.springframework.shell.table.Table; import org.springframework.shell.table.TableBuilder; import org.springframework.stereotype.Component; /** * Stream commands. * * @author Ilayaperumal Gopinathan * @author Mark Fisher */ @Component // todo: reenable optionContext attributes public class StreamCommands implements CommandMarker { private static final String LIST_STREAM = "stream list"; private static final String CREATE_STREAM = "stream create"; 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"; private static final String PROPERTIES_OPTION = "properties"; private static final String PROPERTIES_FILE_OPTION = "propertiesFile"; @Autowired private DataFlowShell dataFlowShell; @Autowired private UserInput userInput; @CliAvailabilityIndicator({ LIST_STREAM, CREATE_STREAM, DEPLOY_STREAM, UNDEPLOY_STREAM, UNDEPLOY_STREAM_ALL, DESTROY_STREAM, DESTROY_STREAM_ALL }) public boolean available() { DataFlowOperations dataFlowOperations = dataFlowShell.getDataFlowOperations(); return dataFlowOperations != null && dataFlowOperations.streamOperations() != null; } @CliCommand(value = LIST_STREAM, help = "List created streams") public Table listStreams() { final PagedResources<StreamDefinitionResource> streams = streamOperations().list(); LinkedHashMap<String, Object> headers = new LinkedHashMap<>(); headers.put("name", "Stream Name"); headers.put("dslText", "Stream Definition"); headers.put("status", "Status"); BeanListTableModel<StreamDefinitionResource> model = new BeanListTableModel<>(streams, headers); return DataFlowTables.applyStyle(new TableBuilder(model)).build(); } @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" }, help = "a stream definition, using the DSL (e.g. \"http --port=9000 | hdfs\")", optionContext = "disable-string-converter completion-stream") String dsl, @CliOption(key = "deploy", help = "whether to deploy the stream immediately", unspecifiedDefaultValue = "false", specifiedDefaultValue = "true") boolean deploy) { streamOperations().createStream(name, dsl, deploy); String message = String.format("Created new stream '%s'", name); if (deploy) { message += "\nDeployment request has been sent"; } return message; } @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 = DeploymentPropertiesUtils.parse(properties); break; case 1: String extension = FilenameUtils.getExtension(propertiesFile.getName()); Properties props = null; if (extension.equals("yaml") || extension.equals("yml")) { YamlPropertiesFactoryBean yamlPropertiesFactoryBean = new YamlPropertiesFactoryBean(); yamlPropertiesFactoryBean.setResources(new FileSystemResource(propertiesFile)); yamlPropertiesFactoryBean.afterPropertiesSet(); props = yamlPropertiesFactoryBean.getObject(); } else { props = new Properties(); try (FileInputStream fis = new FileInputStream(propertiesFile)) { props.load(fis); } } propertiesToUse = DeploymentPropertiesUtils.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("Deployment request has been sent for 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 = 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) { if (force || "y" .equalsIgnoreCase(userInput.promptWithOptions("Really destroy all streams?", "n", "y", "n"))) { streamOperations().destroyAll(); return "Destroyed all streams"; } else { return ""; } } StreamOperations streamOperations() { return dataFlowShell.getDataFlowOperations().streamOperations(); } }