/*
* Copyright 2002-2014 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.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.List;
import org.springframework.shell.core.CommandResult;
import org.springframework.shell.core.JLineShellComponent;
import org.springframework.xd.dirt.rest.PasswordUtils;
import org.springframework.xd.dirt.test.SingleNodeIntegrationTestSupport;
import org.springframework.xd.shell.util.Table;
import org.springframework.xd.shell.util.TableRow;
/**
* Helper methods for stream commands to execute in the shell.
* <p/>
* It should mimic the client side API of StreamOperations as much as possible.
*
* @author Mark Pollack
* @author Mark Fisher
* @author David Turanski
*/
public class StreamCommandsTemplate extends AbstractCommandTemplate {
private List<String> streams = new ArrayList<String>();
/**
* Construct a new StreamCommandTemplate, given a spring shell.
*
* @param shell the spring shell to execute commands against
*/
/* default */
public StreamCommandsTemplate(JLineShellComponent shell, SingleNodeIntegrationTestSupport integrationTestSupport) {
super(shell, integrationTestSupport.streamStateVerifier());
}
/**
* Create and deploy a stream.
*
* Note the name of the stream will be stored so that when the method destroyCreatedStreams is called, the stream
* will be destroyed.
*
* @param streamname the name of the stream
* @param streamdefinition the stream definition DSL
* @param values will be injected into streamdefinition according to {@link String#format(String, Object...)} syntax
*/
public void create(String streamname, String streamdefinition, Object... values) {
doCreate(streamname, streamdefinition, true, values);
}
/**
* Execute stream create (but don't deploy) for the supplied stream name/definition, and verify the command result.
*
* Note the name of the stream will be stored so that when the method destroyCreatedStreams is called, the stream
* will be destroyed.
*
* @param values will be injected into streamdefinition according to {@link String#format(String, Object...)} syntax
*/
public void createDontDeploy(String streamname, String streamdefinition, Object... values) {
doCreate(streamname, streamdefinition, false, values);
}
private void doCreate(String streamname, String streamdefinition, boolean deploy, Object... values) {
String actualDefinition = String.format(streamdefinition, values);
// Shell parser expects quotes to be escaped by \
String wholeCommand = String.format("stream create %s --definition \"%s\" --deploy %s", streamname,
actualDefinition.replaceAll("\"", "\\\\\""), deploy);
CommandResult cr = executeCommand(wholeCommand);
if (deploy) {
stateVerifier.waitForDeploy(streamname);
}
else {
stateVerifier.waitForCreate(streamname);
}
// add the stream name to the streams list before assertion
streams.add(streamname);
String deployMsg = "Created";
if (deploy) {
deployMsg = "Created and deployed";
}
assertEquals(deployMsg + " new stream '" + streamname + "'", cr.getResult());
verifyExists(streamname, actualDefinition, deploy);
}
/**
* Deploy the given stream
*
* @param streamname name of the stream
*/
public void deploy(String streamname) {
CommandResult cr = getShell().executeCommand("stream deploy --name " + streamname);
stateVerifier.waitForDeploy(streamname);
assertTrue("Failure. CommandResult = " + cr.toString(), cr.isSuccess());
assertEquals("Deployed stream '" + streamname + "'", cr.getResult());
}
/**
* Destroy all streams that were created using the 'create' method. Commonly called in a @After annotated method
*/
public void destroyCreatedStreams() {
for (int s = streams.size() - 1; s >= 0; s--) {
String streamname = streams.get(s);
CommandResult cr = executeCommand("stream destroy --name " + streamname);
stateVerifier.waitForDestroy(streamname);
assertTrue("Failure to destroy stream " + streamname + ". CommandResult = " + cr.toString(),
cr.isSuccess());
}
}
/**
* Destroy a specific stream
*
* @param stream The stream to destroy
*/
public void destroyStream(String stream) {
CommandResult cr = executeCommand("stream destroy --name " + stream);
stateVerifier.waitForDestroy(stream);
assertTrue("Failure to destroy stream " + stream + ". CommandResult = " + cr.toString(),
cr.isSuccess());
streams.remove(stream);
}
/**
* Undeploy the given stream name
*
* @param streamname name of the stream.
*/
public void undeploy(String streamname) {
CommandResult cr = getShell().executeCommand("stream undeploy --name " + streamname);
stateVerifier.waitForUndeploy(streamname);
assertTrue(cr.isSuccess());
assertEquals("Un-deployed stream '" + streamname + "'", cr.getResult());
}
/**
* Verify the stream is listed in stream list.
*
* @param streamName the name of the stream
* @param definition definition of the stream
*/
public void verifyExists(String streamName, String definition, boolean deployed) {
final String passwordMaskedDefinition = PasswordUtils.maskPasswordsInDefinition(definition);
CommandResult cr = getShell().executeCommand("stream list");
assertTrue("Failure. CommandResult = " + cr.toString(), cr.isSuccess());
Table t = (Table) cr.getResult();
assertTrue(t.getRows().contains(
new TableRow().addValue(1, streamName).addValue(2, passwordMaskedDefinition.replace("\\\\", "\\")).addValue(
3,
deployed ? "deployed" : "undeployed")));
}
}