From 3c8a34b674c30d1caa6b5d5626cbf1123c99eba8 Mon Sep 17 00:00:00 2001 From: "adrian.f.cole" Date: Tue, 1 Dec 2009 01:04:58 +0000 Subject: [PATCH] Issue 126: added kill git-svn-id: http://jclouds.googlecode.com/svn/trunk@2355 3d8758e0-26b5-11de-8745-db77d3ebf521 --- .../jclouds/scriptbuilder/ScriptBuilder.java | 2 +- .../jclouds/scriptbuilder/domain/Call.java | 2 +- .../domain/InterpretableStatement.java | 2 +- .../jclouds/scriptbuilder/domain/Kill.java | 56 +++++++++++++++++++ .../scriptbuilder/domain/Statement.java | 2 +- .../scriptbuilder/domain/Statements.java | 12 +++- .../jclouds/scriptbuilder/domain/Switch.java | 4 +- .../scriptbuilder/ScriptBuilderTest.java | 22 +++++++- .../test/resources/test_seek_and_destroy.bash | 31 ++++++++++ .../test/resources/test_seek_and_destroy.cmd | 30 ++++++++++ 10 files changed, 155 insertions(+), 8 deletions(-) create mode 100644 scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/Kill.java create mode 100644 scriptbuilder/src/test/resources/test_seek_and_destroy.bash create mode 100644 scriptbuilder/src/test/resources/test_seek_and_destroy.cmd diff --git a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/ScriptBuilder.java b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/ScriptBuilder.java index d34ca651ed..f29587e26d 100644 --- a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/ScriptBuilder.java +++ b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/ScriptBuilder.java @@ -133,7 +133,7 @@ public class ScriptBuilder { new Function>() { @Override public Iterable apply(Statement from) { - return from.functionDependecies(); + return from.functionDependecies(osFamily); } })); List unresolvedFunctions = Lists.newArrayList(dependentFunctions); diff --git a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/Call.java b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/Call.java index e0ee8af4ac..d196a6def5 100644 --- a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/Call.java +++ b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/Call.java @@ -92,7 +92,7 @@ public class Call implements Statement { } @Override - public Iterable functionDependecies() { + public Iterable functionDependecies(OsFamily family) { return ImmutableList.of(function); } } \ No newline at end of file diff --git a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/InterpretableStatement.java b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/InterpretableStatement.java index 8f718d3c5b..c748f3e56e 100644 --- a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/InterpretableStatement.java +++ b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/InterpretableStatement.java @@ -47,7 +47,7 @@ public class InterpretableStatement implements Statement { } @Override - public Iterable functionDependecies() { + public Iterable functionDependecies(OsFamily family) { return ImmutableList.of(); } diff --git a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/Kill.java b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/Kill.java new file mode 100644 index 0000000000..b4fa6e468c --- /dev/null +++ b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/Kill.java @@ -0,0 +1,56 @@ +/** + * + * Copyright (C) 2009 Cloud Conscious, LLC. + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.jclouds.scriptbuilder.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Map; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; + +/** + * Statement used in a shell script + * + * @author Adrian Cole + */ +public class Kill implements Statement { + + public static final Map OS_TO_KILL = ImmutableMap.of(OsFamily.UNIX, + "[ -n \"$FOUND_PID\" ] && {\n echo stopping $FOUND_PID\n kill -9 $FOUND_PID\n}\n", + OsFamily.WINDOWS, + "if defined FOUND_PID (\r\n TASKKILL /F /T /PID %FOUND_PID% >NUL\r\n)\r\n"); + + public Kill() { + } + + public String render(OsFamily family) { + return OS_TO_KILL.get(checkNotNull(family, "family")); + } + + @Override + public Iterable functionDependecies(OsFamily family) { + return ImmutableList.of(); + } +} \ No newline at end of file diff --git a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/Statement.java b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/Statement.java index 80503e855d..f2e8e6aa1f 100644 --- a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/Statement.java +++ b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/Statement.java @@ -29,7 +29,7 @@ package org.jclouds.scriptbuilder.domain; * @author Adrian Cole */ public interface Statement { - Iterable functionDependecies(); + Iterable functionDependecies(OsFamily family); String render(OsFamily family); } \ No newline at end of file diff --git a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/Statements.java b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/Statements.java index 8904a8aa49..66be501a3d 100644 --- a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/Statements.java +++ b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/Statements.java @@ -31,6 +31,7 @@ import java.util.Map; * @author Adrian Cole */ public class Statements { + private static final Kill KILL = new Kill(); public static Statement switchOn(String variable, Map valueToActions) { return new Switch(variable, valueToActions); @@ -41,7 +42,7 @@ public class Statements { } /** - * Stores the pid into the variable foundPid if successful. + * Stores the pid into the variable {@code FOUND_PID} if successful. * * @param args * - what to search for in the process tree. @@ -50,6 +51,15 @@ public class Statements { return new Call("findPid", args); } + /** + * Kills the pid and subprocesses related to the variable {@code FOUND_PID} if set. + * + * @see findPid + */ + public static Statement kill() { + return KILL; + } + public static Statement interpret(String portableStatement) { return new InterpretableStatement(portableStatement); } diff --git a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/Switch.java b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/Switch.java index f1acada635..3a620c4344 100644 --- a/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/Switch.java +++ b/scriptbuilder/src/main/java/org/jclouds/scriptbuilder/domain/Switch.java @@ -127,10 +127,10 @@ public class Switch implements Statement { } @Override - public Iterable functionDependecies() { + public Iterable functionDependecies(OsFamily family) { List functions = Lists.newArrayList(); for (Statement statement : valueToActions.values()) { - Iterables.addAll(functions, statement.functionDependecies()); + Iterables.addAll(functions, statement.functionDependecies(family)); } return functions; } diff --git a/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/ScriptBuilderTest.java b/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/ScriptBuilderTest.java index 2de7189633..1b1c0d7286 100644 --- a/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/ScriptBuilderTest.java +++ b/scriptbuilder/src/test/java/org/jclouds/scriptbuilder/ScriptBuilderTest.java @@ -1,6 +1,9 @@ package org.jclouds.scriptbuilder; -import static org.jclouds.scriptbuilder.domain.Statements.*; +import static org.jclouds.scriptbuilder.domain.Statements.findPid; +import static org.jclouds.scriptbuilder.domain.Statements.interpret; +import static org.jclouds.scriptbuilder.domain.Statements.kill; +import static org.jclouds.scriptbuilder.domain.Statements.switchOn; import static org.testng.Assert.assertEquals; import java.io.IOException; @@ -60,6 +63,23 @@ public class ScriptBuilderTest { + ShellToken.SH.to(OsFamily.UNIX)), Charsets.UTF_8))); } + ScriptBuilder seekAndDestroyBuilder = new ScriptBuilder().addStatement(findPid("{args}")) + .addStatement(kill()); + + @Test + public void testSeekAndDestroyWindows() throws MalformedURLException, IOException { + assertEquals(seekAndDestroyBuilder.build(OsFamily.WINDOWS), CharStreams.toString(Resources + .newReaderSupplier(Resources.getResource("test_seek_and_destroy." + + ShellToken.SH.to(OsFamily.WINDOWS)), Charsets.UTF_8))); + } + + @Test + public void testSeekAndDestroyUNIX() throws MalformedURLException, IOException { + assertEquals(seekAndDestroyBuilder.build(OsFamily.UNIX), CharStreams.toString(Resources + .newReaderSupplier(Resources.getResource("test_seek_and_destroy." + + ShellToken.SH.to(OsFamily.UNIX)), Charsets.UTF_8))); + } + @Test public void testSwitchOn() { ScriptBuilder builder = new ScriptBuilder(); diff --git a/scriptbuilder/src/test/resources/test_seek_and_destroy.bash b/scriptbuilder/src/test/resources/test_seek_and_destroy.bash new file mode 100644 index 0000000000..0fc6e2f1af --- /dev/null +++ b/scriptbuilder/src/test/resources/test_seek_and_destroy.bash @@ -0,0 +1,31 @@ +#!/bin/bash +set +u +shopt -s xpg_echo +shopt -s expand_aliases +unset PATH JAVA_HOME LD_LIBRARY_PATH +function abort { + echo "aborting: $@" 1>&2 + exit 1 +} +function findPid { + unset FOUND_PID; + [ $# -eq 1 ] || { + abort "findPid requires a parameter of pattern to match" + return 1 + } + local PATTERN="$1"; shift + local _FOUND=`ps auxwww|grep "$PATTERN"|grep -v " $0"|grep -v grep|awk '{print $2}'` + [ -n "$_FOUND" ] && { + export FOUND_PID=$_FOUND + return 0 + } || { + return 1 + } +} +export PATH=/usr/ucb/bin:/bin:/usr/bin:/usr/sbin +findPid $@ || exit 1 +[ -n "$FOUND_PID" ] && { + echo stopping $FOUND_PID + kill -9 $FOUND_PID +} +exit 0 diff --git a/scriptbuilder/src/test/resources/test_seek_and_destroy.cmd b/scriptbuilder/src/test/resources/test_seek_and_destroy.cmd new file mode 100644 index 0000000000..79c41c166e --- /dev/null +++ b/scriptbuilder/src/test/resources/test_seek_and_destroy.cmd @@ -0,0 +1,30 @@ +@echo off +set PATH= +set JAVA_HOME= +set PATH= +GOTO FUNCTION_END +:abort + echo aborting: %EXCEPTION% + exit /b 1 +:findPid + set FOUND_PID= + set _expression=%1 + shift + set FIND_PROCESS=TASKLIST /FI "WINDOWTITLE eq %_expression%" /NH + FOR /F "usebackq tokens=2 delims= " %%A IN (`cmd /c "%FIND_PROCESS% 2>NUL"`) DO ( + SET FOUND_PID=%%A + ) + if defined FOUND_PID ( + exit /b 0 + ) else ( + set EXCEPTION=%_expression% not found + exit /b 1 + ) +:FUNCTION_END +set PATH=c:\windows\;C:\windows\system32;c:\windows\system32\wbem +call :findPid %* +if errorlevel 1 goto abort +if defined FOUND_PID ( + TASKKILL /F /T /PID %FOUND_PID% >NUL +) +exit /b 0