This is an automated email from the ASF dual-hosted git repository. heneveld pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/brooklyn-server.git
commit b81787c28be0f37ddd57e450eaed1d13710702b2 Author: Alex Heneveld <[email protected]> AuthorDate: Fri Jul 29 02:08:40 2022 +0100 refactor BashCommands to have non-static, context sensitive evaluation in particular allowing whether to ignoreCerts to be configurable via mgmt properties or entity config --- .../util/core/file/BrooklynOsCommands.java | 52 + .../org/apache/brooklyn/util/ssh/BashCommands.java | 1070 +++++--------------- ...Commands.java => BashCommandsConfigurable.java} | 234 ++--- .../apache/brooklyn/util/ssh/IptablesCommands.java | 142 +-- ...ands.java => IptablesCommandsConfigurable.java} | 75 +- 5 files changed, 527 insertions(+), 1046 deletions(-) diff --git a/core/src/main/java/org/apache/brooklyn/util/core/file/BrooklynOsCommands.java b/core/src/main/java/org/apache/brooklyn/util/core/file/BrooklynOsCommands.java new file mode 100644 index 0000000000..54ecd2a9f7 --- /dev/null +++ b/core/src/main/java/org/apache/brooklyn/util/core/file/BrooklynOsCommands.java @@ -0,0 +1,52 @@ +/* + * 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.apache.brooklyn.util.core.file; + +import org.apache.brooklyn.api.entity.Entity; +import org.apache.brooklyn.api.mgmt.ManagementContext; +import org.apache.brooklyn.config.ConfigKey; +import org.apache.brooklyn.core.config.ConfigKeys; +import org.apache.brooklyn.core.entity.EntityInternal; +import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal; +import org.apache.brooklyn.util.ssh.BashCommandsConfigurable; +import org.apache.brooklyn.util.ssh.IptablesCommandsConfigurable; + +public class BrooklynOsCommands { + + public static final ConfigKey<Boolean> OS_COMMANDS_IGNORE_CERTS = ConfigKeys.newBooleanConfigKey("brooklyn.os.commands.ignoreCerts", "Whether to generate OS commands that ignore certs, e.g. curl -k"); + + public static BashCommandsConfigurable bash(ManagementContext mgmt) { + return BashCommandsConfigurable.newInstance().withIgnoreCerts( ((ManagementContextInternal)mgmt).getBrooklynProperties().getConfig(OS_COMMANDS_IGNORE_CERTS) ); + } + + public static IptablesCommandsConfigurable bashIptables(ManagementContext mgmt) { + return new IptablesCommandsConfigurable(bash(mgmt)); + } + + public static BashCommandsConfigurable bash(Entity entity) { + Boolean ignoreCerts = entity.config().get(OS_COMMANDS_IGNORE_CERTS); + if (ignoreCerts!=null) return BashCommandsConfigurable.newInstance().withIgnoreCerts(ignoreCerts); + return bash( ((EntityInternal)entity).getManagementContext() ); + } + + public static IptablesCommandsConfigurable bashIptables(Entity entity) { + return new IptablesCommandsConfigurable(bash(entity)); + } + +} diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/ssh/BashCommands.java b/utils/common/src/main/java/org/apache/brooklyn/util/ssh/BashCommands.java index d60c9a9a35..4bd36ba31a 100644 --- a/utils/common/src/main/java/org/apache/brooklyn/util/ssh/BashCommands.java +++ b/utils/common/src/main/java/org/apache/brooklyn/util/ssh/BashCommands.java @@ -18,812 +18,284 @@ */ package org.apache.brooklyn.util.ssh; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; -import static java.lang.String.format; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import org.apache.brooklyn.util.collections.MutableMap; -import org.apache.brooklyn.util.text.Identifiers; -import org.apache.brooklyn.util.text.Strings; -import org.apache.brooklyn.util.text.StringEscapes.BashStringEscapes; -import org.apache.brooklyn.util.time.Duration; - import com.google.common.annotations.Beta; import com.google.common.base.Joiner; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; +import org.apache.brooklyn.util.collections.MutableMap; +import org.apache.brooklyn.util.text.Identifiers; +import org.apache.brooklyn.util.text.StringEscapes.BashStringEscapes; +import org.apache.brooklyn.util.text.Strings; +import org.apache.brooklyn.util.time.Duration; + +import java.util.*; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static java.lang.String.format; public class BashCommands { - /** - * Returns a string for checking whether the given executable is available, - * and installing it if necessary. - * <p/> - * Uses {@link #installPackage} and accepts the same flags e.g. for apt, yum, rpm. - */ - public static String installExecutable(Map<?,?> flags, String executable) { - return onlyIfExecutableMissing(executable, installPackage(flags, executable)); - } - - public static String installExecutable(String executable) { - return installExecutable(MutableMap.of(), executable); - } - - /** - * Returns a command with all output redirected to /dev/null - */ - public static String quiet(String command) { - return format("(%s > /dev/null 2>&1)", command); - } - - /** - * Returns a command that always exits successfully - */ - public static String ok(String command) { - return String.format("(%s || true)", command); - } - - /** - * Returns a command for safely running as root, using {@code sudo}. - * <p/> - * Ensuring non-blocking if password not set by using - * {@code -n} which means to exit if password required - * (this is unsupported in Ubuntu 8 but all modern OS's seem okay with this!), - * and (perhaps unnecessarily ?) - * {@code -S} which reads from stdin (routed to {@code /dev/null}, it was claimed here previously, though I'm not sure?). - * <p/> - * Also specify {@code -E} to pass the parent environment in. - * <p/> - * If already root, simply runs the command, wrapped in brackets in case it is backgrounded. - * <p/> - * The command is not quoted or escaped in any ways. - * If you are doing privileged redirect you may need to pass e.g. "bash -c 'echo hi > file'". - * <p/> - * If null is supplied, it is returned (sometimes used to indicate no command desired). - */ - public static String sudo(String command) { - if (command==null) return null; - if (command.startsWith("( ") || command.endsWith(" &")) - return sudoNew(command); - else - return sudoOld(command); - } - - public static String authSudo(String command, String password) { - checkNotNull(password, "password must not be null"); - if (command==null) return null; - if (command.startsWith("( ") || command.endsWith(" &")) { - throw new UnsupportedOperationException("authSudo supports only simple commands, not those wrapped in parentheses or backgrounded: cmd="+command); - } - // some OS's (which?) fail if you try running sudo when you're already root (dumb but true) - return format("( if test \"$UID\" -eq 0; then ( %s ); else echo -e '%s\\n' | sudo -E -S -- %s; fi )", command, password, command); - } - - // TODO would like to move away from sudoOld -- but needs extensive testing! - - private static String sudoOld(String command) { - if (command==null) return null; - // some OS's (which?) fail if you try running sudo when you're already root (dumb but true) - return format("( if test \"$UID\" -eq 0; then ( %s ); else sudo -E -n -S -- %s; fi )", command, command); - } - private static String sudoNew(String command) { - if (command==null) return null; - // on some OS's e.g. Centos 6.5 in SL, sudo -- X tries to run X as a literal argument; - // in particular "( echo foo && echo bar )" fails when passed as an argument in that way, - // but works if passed to bash -c; - // but others e.g. OS X fail if you say sudo -- bash -c "( echo foo )" ... not liking the parentheses - // piping to sudo bash seems the most reliable way - return "( if test \"$UID\" -eq 0; then ( "+command+" ); else " - + "echo " + BashStringEscapes.wrapBash(command) + " | " - + "sudo -E -n -S -s -- bash" - + " ; fi )"; - } - - /** sudo to a given user and run the indicated command; - * @deprecated since 0.7.0 semantics of this are fiddly, e.g. whether user gets their environment */ - @Deprecated - @Beta - public static String sudoAsUser(String user, String command) { - return sudoAsUserOld(user, command); - } - - private static String sudoAsUserOld(String user, String command) { - if (command == null) return null; - return format("{ sudo -E -n -u %s -s -- %s ; }", user, command); - } - // TODO would like to move away from sudoOld -- but needs extensive testing! -// private static String sudoAsUserNew(String user, String command) { -// if (command == null) return null; -// // no -E, run with permissions of this user -// // FIXME still doesn't always work e.g. doesn't have path of user -// // (Alex says: can't find any combinations which work reliably) -// return "{ sudo -n -S -i -u "+user+" -- "+BashStringEscapes.wrapBash(command)+" ; }"; -// } - - public static String addSbinPathCommand() { - return "export PATH=" + sbinPath(); - } - - public static String sbinPath() { - return "$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"; - } - - /** executes a command, then as user tees the output to the given file. - * useful e.g. for appending to a file which is only writable by root or a priveleged user. */ - public static String executeCommandThenAsUserTeeOutputToFile(String commandWhoseOutputToWrite, String user, String file) { - return format("{ %s | sudo -E -n -u %s -s -- tee -a %s ; }", - commandWhoseOutputToWrite, user, file); - } - - /** - * Some machines require a TTY for sudo. Brooklyn by default does not use a TTY - * so that it can get separate STDERR and STDOUT streams. You can enable a TTY as an - * option to every SSH command, or you can do it once and modify the machine so that - * a TTY is not subsequently required. If this task has already been executed it - * will try to detect the changes and do nothing. - * <p> - * This command must be run with allocatePTY set as a flag to ssh. - * See {@link SshTasks#dontRequireTtyForSudo(SshMachineLocation, OnFailingTask)} which sets that up. - * <p> - * Having a TTY for sudo seems like another case of imaginary security which is just irritating. - * Like water restrictions at airport security. - */ - public static String dontRequireTtyForSudo() { - String sudoersFileName = "/etc/sudoers"; - String tmpSuffix = Identifiers.makeRandomLowercaseId(6); // Avoid clobbering - - // Visudo's quiet mode (-q) is not enabled. visudo's output is used for diagnostic purposes - return ifFileExistsElse0(sudoersFileName, - alternatives( - sudo(format("grep brooklyn-removed-require-tty %s", sudoersFileName)), - chainGroup( - sudo(format("cp %1$s %1$s.%2$s", sudoersFileName, tmpSuffix)), - sudo(format("sed -i.brooklyn.bak 's/.*requiretty.*/#brooklyn-removed-require-tty/' %1$s.%2$s", sudoersFileName, tmpSuffix)), - sudo(format("visudo -c -f %1$s.%2$s", sudoersFileName, tmpSuffix)), - sudo(format("mv %1$s.%2$s %1$s", sudoersFileName, tmpSuffix))))); - } - - /** generates ~/.ssh/id_rsa if that file does not exist */ - public static String generateKeyInDotSshIdRsaIfNotThere() { - return "[ -f ~/.ssh/id_rsa ] || ( mkdir -p ~/.ssh ; chmod 700 ~/.ssh ; ssh-keygen -t rsa -N '' -f ~/.ssh/id_rsa )"; - } - - // TODO a builder would be better than these ifBlahExistsElseBlah methods! - // (ideally formatting better also; though maybe SshTasks would be better?) - - /** - * Returns a command that runs only if the specified file (or link or directory) exists; - * if the command runs and fails that exit is preserved (but if the file does not exist exit code is zero). - * Executed as { { not-file-exists && ok ; } || command ; } for portability. - * ("if [ ... ] ; then xxx ; else xxx ; fi" syntax is not quite as portable, I seem to recall (not sure, Alex Aug 2013).) - */ - public static String ifFileExistsElse0(String path, String command) { - return alternativesGroup( - chainGroup(format("test ! -e %s", path), "true"), - command); - } - /** as {@link #ifFileExistsElse0(String, String)} but returns non-zero if the test fails (also returns non-zero if the command fails, - * so you can't tell the difference :( -- we need if ; then ; else ; fi semantics for that I think, but not sure how portable that is) */ - public static String ifFileExistsElse1(String path, String command) { - return chainGroup(format("test -e %s", path), command); - } - - /** - * Returns a command that runs only if the specified executable exists on the path (using `which`). - * if the command runs and fails that exit is preserved (but if the executable is not on the path exit code is zero). - * @see #ifFileExistsElse0(String, String) for implementation discussion, using <code>{ { test -z `which executable` && true ; } || command ; } - */ - public static String ifExecutableElse0(String executable, String command) { - return alternativesGroup( - chainGroup(format("test -z `which %s`", executable), "true"), - command); - } - - /** as {@link #ifExecutableElse0(String, String)} but returns 1 if the test fails (also returns non-zero if the command fails) */ - public static String ifExecutableElse1(String executable, String command) { - return chainGroup(format("which %s", executable), command); - } - - /** - * Returns a command which - * executes <code>statement</code> only if <code>command</code> is NOT found in <code>$PATH</code> - * - * @param command - * @param statement - * @return command - */ - public static String ifNotExecutable(String command, String statement) { - return String.format("{ { test ! -z `which %s`; } || { %s; } }", command, statement); - } - - /** - * Returns a command that runs only if the specified executable exists on the path (using `which`). - * if the command runs and fails that exit is preserved (but if the executable is not on the path exit code is zero). - * @see #ifFileExistsElse0(String, String) for implementation discussion, using <code>{ { test -z `which executable` && true ; } || command ; } - */ - public static String onlyIfExecutableMissing(String executable, String command) { - return alternativesGroup(format("which %s", executable), command); - } - - /** - * @deprecated As of release 0.10.0, replaced by {@link #ifExecutableDoesNotExistElse(String, String, String)} - */ - @Deprecated - public static String ifExecutableElse(String command, String ifNotExist, String ifExist) { - return ifExecutableDoesNotExistElse(command, ifNotExist, ifExist); - } - - public static String ifExecutableDoesNotExistElse(String command, String ifNotExist, String ifExist) { - return com.google.common.base.Joiner.on('\n').join( - ifExecutableDoesNotExistElse(command, ImmutableList.<String>of(ifNotExist), ImmutableList.<String>of(ifExist))); - } - - /** - * @deprecated As of release 0.10.0, replaced by {@link #ifExecutableDoesNotExistElse(String, List, List)} - */ - @Deprecated - public static ImmutableList<String> ifExecutableElse(String command, List<String> ifNotExist, List<String> ifExist) { - return ifExecutableDoesNotExistElse(command, ifNotExist, ifExist); - } - - public static ImmutableList<String> ifExecutableDoesNotExistElse(String command, List<String> ifNotExist, List<String> ifExist) { - return ImmutableList.<String>builder() - .add(String.format("if test -z `which %s`; then", command)) - .addAll(ifNotExist) - .add("else") - .addAll(ifExist) - .add("fi") - .build(); - } - - /** - * Returns a sequence of chained commands that runs until one of them fails (i.e. joined by '&&') - * This currently runs as a subshell (so exits are swallowed) but behaviour may be changed imminently. - * (Use {@link #chainGroup(Collection)} or {@link #chainSubshell(Collection)} to be clear.) - */ - public static String chain(Collection<String> commands) { - return "( " + Strings.join(commands, " && ") + " )"; - } - - /** Convenience for {@link #chain(Collection)} */ - public static String chain(String ...commands) { - return "( " + Strings.join(commands, " && ") + " )"; - } - - /** As {@link #chain(Collection)}, but explicitly using { } grouping characters - * to ensure exits are propagated. */ - public static String chainGroup(Collection<String> commands) { - // spaces required around curly braces - return "{ " + Strings.join(commands, " && ") + " ; }"; - } - - /** As {@link #chainGroup(Collection)} */ - public static String chainGroup(String ...commands) { - return "{ " + Strings.join(commands, " && ") + " ; }"; - } - - /** As {@link #chain(Collection)}, but explicitly using ( ) grouping characters - * to ensure exits are caught. */ - public static String chainSubshell(Collection<String> commands) { - // the spaces are not required, but it might be possible that a (( expr )) is interpreted differently - // (won't hurt to have the spaces in any case!) - return "( " + Strings.join(commands, " && ") + " )"; - } - - /** As {@link #chainSubshell(Collection)} */ - public static String chainSubshell(String ...commands) { - return "( " + Strings.join(commands, " && ") + " )"; - } - - /** - * Returns a sequence of chained commands that runs until one of them succeeds (i.e. joined by '||'). - * This currently runs as a subshell (so exits are swallowed) but behaviour may be changed imminently. - * (Use {@link #alternativesGroup(Collection)} or {@link #alternativesSubshell(Collection)} to be clear.) - */ - public static String alternatives(Collection<String> commands) { - return "( " + Strings.join(commands, " || ") + " )"; - } - - /** As {@link #alternatives(Collection)} */ - public static String alternatives(String ...commands) { - return "( " + Strings.join(commands, " || ") + " )"; - } - - /** As {@link #alternatives(Collection)}, but explicitly using { } grouping characters - * to ensure exits are propagated. */ - public static String alternativesGroup(Collection<String> commands) { - // spaces required around curly braces - return "{ " + Strings.join(commands, " || ") + " ; }"; - } - - /** As {@link #alternativesGroup(Collection)} */ - public static String alternativesGroup(String ...commands) { - return "{ " + Strings.join(commands, " || ") + " ; }"; - } - - /** As {@link #alternatives(Collection)}, but explicitly using ( ) grouping characters - * to ensure exits are caught. */ - public static String alternativesSubshell(Collection<String> commands) { - // the spaces are not required, but it might be possible that a (( expr )) is interpreted differently - // (won't hurt to have the spaces in any case!) - return "( " + Strings.join(commands, " || ") + " )"; - } - - /** As {@link #alternativesSubshell(Collection)} */ - public static String alternativesSubshell(String ...commands) { - return "( " + Strings.join(commands, " || ") + " )"; - } - - /** returns the pattern formatted with the given arg if the arg is not null, otherwise returns null */ - public static String formatIfNotNull(String pattern, Object arg) { - if (arg==null) return null; - return format(pattern, arg); - } - - public static String installPackage(String packageDefaultName) { - return installPackage(MutableMap.of(), packageDefaultName); - } - /** - * Returns a command for installing the given package. - * <p> - * Warns, but does not fail or return non-zero if it ultimately fails. - * <p> - * Flags can contain common overrides for {@code apt}, {@code yum}, {@code port} and {@code brew} - * as the package names can be different for each of those. Setting the default package name to - * {@literal null} will use only the overridden package manager values. The {@code onlyifmissing} flag - * adds a check for an executable, and only attempts to install packages if it is not found. - * <pre> - * installPackage(ImmutableMap.of("yum", "openssl-devel", "apt", "openssl libssl-dev zlib1g-dev"), "libssl-devel"); - * installPackage(ImmutableMap.of("apt", "libaio1"), null); - * installPackage(ImmutableMap.of("onlyifmissing", "curl"), "curl"); - * </pre> - */ - public static String installPackage(Map<?,?> flags, String packageDefaultName) { - return installPackageOr(flags, packageDefaultName, null); - } - public static String installPackageOrFail(Map<?,?> flags, String packageDefaultName) { - return installPackageOr(flags, packageDefaultName, "exit 9"); - } - public static String installPackageOr(Map<?,?> flags, String packageDefaultName, String optionalCommandToRunIfNone) { - String ifMissing = (String) flags.get("onlyifmissing"); - String zypperInstall = formatIfNotNull("zypper --non-interactive --no-gpg-checks install %s", getFlag(flags, "zypper", packageDefaultName)); - String aptInstall = formatIfNotNull("apt-get install -y --allow-unauthenticated %s", getFlag(flags, "apt", packageDefaultName)); - String yumInstall = formatIfNotNull("yum -y --nogpgcheck install %s", getFlag(flags, "yum", packageDefaultName)); - String brewInstall = formatIfNotNull("brew install %s", getFlag(flags, "brew", packageDefaultName)); - String portInstall = formatIfNotNull("port install %s", getFlag(flags, "port", packageDefaultName)); - - List<String> commands = new LinkedList<String>(); - if (ifMissing != null) - commands.add(format("which %s", ifMissing)); - if (zypperInstall != null) - commands.add(ifExecutableElse1("zypper", - chainGroup( - "echo zypper exists, doing refresh", - ok(sudo("zypper --non-interactive --no-gpg-checks refresh")), - sudo(zypperInstall)))); - if (aptInstall != null) - commands.add(ifExecutableElse1("apt-get", - chainGroup( - "echo apt-get exists, doing update", - "export DEBIAN_FRONTEND=noninteractive", - ok(sudo("apt-get update")), - sudo(aptInstall)))); - if (yumInstall != null) - // Need to upgrade ca-certificates sometimes: - // http://serverfault.com/questions/637549/epel-repo-for-centos-6-causing-error?newreg=7c6019c0d0ae483c8bb3af387166ce49 - commands.add(ifExecutableElse1("yum", - chainGroup( - "echo yum exists, doing update", - ok(sudo("yum check-update")), - ok(sudo("yum -y install epel-release")), - ok(sudo("yum upgrade -y ca-certificates --disablerepo=epel")), - sudo(yumInstall)))); - if (brewInstall != null) - commands.add(ifExecutableElse1("brew", brewInstall)); - if (portInstall != null) - commands.add(ifExecutableElse1("port", sudo(portInstall))); - - String lastCommand = ok(warn("WARNING: no known/successful package manager to install " + - (packageDefaultName!=null ? packageDefaultName : flags.toString()) + - ", may fail subsequently")); - if (optionalCommandToRunIfNone != null) - lastCommand = chain(lastCommand, optionalCommandToRunIfNone); - commands.add(lastCommand); - - return alternatives(commands); - } - - public static String warn(String message) { - return "( echo "+BashStringEscapes.wrapBash(message)+" | tee /dev/stderr )"; - } - - /** returns a command which logs a message to stdout and stderr then exits with the given error code */ - public static String fail(String message, int code) { - return chainGroup(warn(message), "exit "+code); - } - - /** requires the command to have a non-zero exit code; e.g. - * <code>require("which foo", "Command foo must be found", 1)</code> */ - public static String require(String command, String failureMessage, int exitCode) { - return alternativesGroup(command, fail(failureMessage, exitCode)); - } - - /** as {@link #require(String, String, int)} but returning the original exit code */ - public static String require(String command, String failureMessage) { - return alternativesGroup(command, chainGroup("EXIT_CODE=$?", warn(failureMessage), "exit $EXIT_CODE")); - } - - /** requires the test to pass, as valid bash `test` arguments; e.g. - * <code>requireTest("-f /etc/hosts", "Hosts file must exist", 1)</code> */ - public static String requireTest(String test, String failureMessage, int exitCode) { - return require("test "+test, failureMessage, exitCode); - } - - /** as {@link #requireTest(String, String, int)} but returning the original exit code */ - public static String requireTest(String test, String failureMessage) { - return require("test "+test, failureMessage); - } - - /** fails with nice error if the given file does not exist */ - public static String requireFile(String file) { - return requireTest("-f "+BashStringEscapes.wrapBash(file), "The required file \""+file+"\" does not exist"); - } - - /** fails with nice error if the given file does not exist */ - public static String requireExecutable(String command) { - return require("which "+BashStringEscapes.wrapBash(command), "The required executable \""+command+"\" does not exist"); - } - - public static String waitForFileContents(String file, String desiredContent, Duration timeout, boolean failOnTimeout) { - long secs = Math.max(timeout.toSeconds(), 1); - - List<String> commands = ImmutableList.of( - "for i in {1.."+secs+"}; do", - " grep '"+desiredContent+"' "+file+" && result=0 || result=$?", - " [ \"$result\" == 0 ] && break", - " sleep 1", - "done", - "if test \"$result\" -ne 0; then", - " ls -l "+file+" || true", - " cat "+file+" || true", - " "+ (failOnTimeout ? - "echo \"Couldn't find "+desiredContent+" in "+file+"; aborting\" && exit 1" : - "echo \"Couldn't find "+desiredContent+" in "+file+"; continuing\""), - "fi"); - return Joiner.on("\n").join(commands); - } - - public static String waitForFileExists(String file, Duration timeout, boolean failOnTimeout) { - long secs = Math.max(timeout.toSeconds(), 1); - - List<String> commands = ImmutableList.of( - "for i in {1.."+secs+"}; do", - " [[ -f "+file+" ]] && result=0 || result=$?", - " [ \"$result\" == 0 ] && break", - " sleep 1", - "done", - "if test \"$result\" -ne 0; then", - " "+ (failOnTimeout ? - "echo \"Couldn't find file "+file+"; aborting\" && exit 1" : - "echo \"Couldn't find file "+file+"; continuing\""), - "fi"); - return Joiner.on("\n").join(commands); - } - - public static String waitForPortFree(int port, Duration timeout, boolean failOnTimeout) { - long secs = Math.max(timeout.toSeconds(), 1); - - // TODO How platform-dependent are the args + output format of netstat? - // TODO Not using sudo as wrapping either netstat call or sudo(alternativesGroup(...)) fails; parentheses too confusing! - String netstatCommand = alternativesGroup( - "sudo netstat -antp --tcp", // for Centos - "sudo netstat -antp TCP"); // for OS X - - // number could appear in an IP address or as a port; look for white space at end, and dot or colon before - String grepCommand = "grep -E '(:|\\.)"+port+"($|\\s)' > /dev/null"; - - List<String> commands = ImmutableList.of( - "for i in {1.."+secs+"}; do", - " "+BashCommands.requireExecutable("netstat"), - " "+alternativesGroup( - chainGroup("which awk", "AWK_EXEC=awk"), - chainGroup("which gawk", "AWK_EXEC=gawk"), - chainGroup("which /usr/bin/awk", "AWK_EXEC=/usr/bin/awk"), - chainGroup("echo \"No awk to determine if Port "+port+" still in use; aborting\"", "exit 1")), - " "+netstatCommand+" | $AWK_EXEC '{print $4}' | "+grepCommand+" && result=0 || result=$?", - " [ \"$result\" != 0 ] && break", - " sleep 1", - "done", - "if test \"$result\" -eq 0; then", - " "+ (failOnTimeout ? - "echo \"Port "+port+" still in use (according to netstat); aborting\" && exit 1" : - "echo \"Port "+port+" still in use (according to netstat); continuing\""), - "fi"); - return Joiner.on("\n").join(commands); - } - - public static String unzip(String file, String targetDir) { - return "unzip " + file + (Strings.isNonBlank(targetDir) ? " -d "+targetDir : ""); - } - - public static final String INSTALL_TAR = installExecutable("tar"); - public static final String INSTALL_CURL = installExecutable("curl"); - public static final String INSTALL_WGET = installExecutable("wget"); - public static final String INSTALL_ZIP = installExecutable("zip"); - public static final String INSTALL_UNZIP = alternatives(installExecutable("unzip"), installExecutable("zip")); - public static final String INSTALL_SYSSTAT = installPackage(ImmutableMap.of("onlyifmissing", "iostat"), "sysstat"); - - /** - * Returns commands to download the URL, saving as the given file. Will try each URL in turn until one is successful - * (see `curl -f` documentation). - */ - public static List<String> commandsToDownloadUrlsAs(List<String> urls, String saveAs) { - return Arrays.asList(INSTALL_CURL, - require(simpleDownloadUrlAs(urls, saveAs), "Could not retrieve "+saveAs+". Tried: " + Joiner.on(", ").join(urls), 9)); - } - - /** - * Returns commands to download the URL, saving as the given file. Will try each URL in turn until one is successful. - * It allows setting a minimum TLS version to avoid this error: <code> <curl: (35) Peer reports incompatible or unsupported protocol version./code> - * (see `curl -f` documentation). - */ - public static List<String> commandsToDownloadUrlsAsWithMinimumTlsVersion(List<String> urls, String saveAs, String tlsVersion) { - return Arrays.asList(INSTALL_CURL, - require(simpleDownloadUrlAs(urls, saveAs, tlsVersion), "Could not retrieve "+saveAs+". Tried: " + Joiner.on(", ").join(urls), 9)); - } - - public static String commandToDownloadUrlsAs(List<String> urls, String saveAs) { - return chain(INSTALL_CURL, - require(simpleDownloadUrlAs(urls, saveAs), "Could not retrieve "+saveAs+". Tried: " + Joiner.on(", ").join(urls), 9)); - } - public static String commandToDownloadUrlAs(String url, String saveAs) { - return chain(INSTALL_CURL, - require(simpleDownloadUrlAs(Arrays.asList(url), saveAs), "Could not retrieve "+saveAs+" from " + url, 9)); - } - - /** - * Returns command to download the URL, sending the output to stdout -- - * suitable for redirect by appending " | tar xvf". - * Will try each URL in turn until one is successful - */ - public static String downloadToStdout(List<String> urls) { - return chain( - INSTALL_CURL + " > /dev/null", - require(simpleDownloadUrlAs(urls, null), - "Could not retrieve file. Tried: " + Joiner.on(", ").join(urls), 9)); - } - - /** as {@link #downloadToStdout(List)} but varargs for convenience */ - public static String downloadToStdout(String ...urls) { - return downloadToStdout(Arrays.asList(urls)); - } - - /** - * Same as {@link simpleDownloadUrlAs(List, String)}, except does not install curl, and does not exit on failure, - * and if saveAs is null it downloads it so stdout. - */ - public static String simpleDownloadUrlAs(List<String> urls, String saveAs) { - return simpleDownloadUrlAs(urls, null, null, saveAs, null); - } - - /** - * Same as {@link simpleDownloadUrlAs(List, String, String)}, except does not install curl, and does not exit on failure, - * and if saveAs is null it downloads it so stdout. - */ - public static String simpleDownloadUrlAs(List<String> urls, String saveAs, String tlsVersion) { - return simpleDownloadUrlAs(urls, null, null, saveAs, tlsVersion); - } - - public static String simpleDownloadUrlAs(List<String> urls, String user, String password, String saveAs, String tlsVersion) { - if (urls.isEmpty()) throw new IllegalArgumentException("No URLs supplied to download "+saveAs); - - List<String> commands = new ArrayList<String>(); - for (String url : urls) { - String command = tlsVersion == null ? - "curl -f -L -k --retry 10 --keepalive-time 30 --speed-time 30 " : - "curl --tlsv" + tlsVersion + " -f -L -k --retry 10 --keepalive-time 30 --speed-time 30 " ; - if (user!=null && password!=null) { - command = command + format("-u %s:%s ", user, password); - } - command = command + format("\"%s\"", url); - if (saveAs!=null) { - command = command + format(" -o %s", saveAs); - } - commands.add(command); - } - return alternatives(commands); - } - - private static Object getFlag(Map<?,?> flags, String flagName, Object defaultValue) { - Object found = flags.get(flagName); - return found == null ? defaultValue : found; - } - - /** - * Install a particular Java runtime, fails if not possible. - * <p> - * <em><strong>Note</strong> Java 8 is not yet supported on SUSE</em> - * - * @return The command to install the given Java runtime. - * @see #installJava6OrFail() - * @see #installJava7Or6OrFail() - * @see #installJavaLatestOrFail() - */ - public static String installJava(int version) { - Preconditions.checkArgument(version == 6 || version == 7 || version == 8, "Supported Java versions are 6, 7, or 8"); - List<String> commands = new LinkedList<String>(); - commands.add(ok(addOpenJDKPPK())); - commands.add(installPackageOr(MutableMap.of("apt", "openjdk-" + version + "-jdk","yum", "java-1." + version + ".0-openjdk-devel"), null, - ifExecutableElse1("zypper", chainGroup( - ok(sudo("zypper --non-interactive addrepo http://download.opensuse.org/repositories/Java:/openjdk6:/Factory/SLE_11_SP3 java_sles_11")), - ok(sudo("zypper --non-interactive addrepo http://download.opensuse.org/repositories/Java:/openjdk6:/Factory/openSUSE_11.4 java_suse_11")), - ok(sudo("zypper --non-interactive addrepo http://download.opensuse.org/repositories/Java:/openjdk6:/Factory/openSUSE_12.3 java_suse_12")), - ok(sudo("zypper --non-interactive addrepo http://download.opensuse.org/repositories/Java:/openjdk6:/Factory/openSUSE_13.1 java_suse_13")), - alternatives(installPackageOrFail(MutableMap.of("zypper", "java-1_" + version + "_0-openjdk-devel"), null), - installPackageOrFail(MutableMap.of("zypper", "java-1_" + version + "_0-ibm"), null)))))); - commands.add(ok(upgradeNSS())); - return chainGroup(commands); - } - - public static String installJava6() { - return installJava(6); - } - public static String installJava7() { - return installJava(7); - } - public static String installJava8() { - return installJava(8); - } - - public static String installJava6IfPossible() { - return ok(installJava6()); - } - public static String installJava7IfPossible() { - return ok(installJava7()); - } - public static String installJava8IfPossible() { - return ok(installJava8()); - } - - public static String installJava6OrFail() { - return alternatives(installJava6(), fail("java 6 install failed", 9)); - } - public static String installJava7OrFail() { - return alternatives(installJava7(), fail("java 7 install failed", 9)); - } - public static String installJava7Or6OrFail() { - return alternatives(installJava7(), installJava6(), fail("java install failed", 9)); - } - public static String installJavaLatestOrFail() { - return alternatives(installJava8(), installJava7(), installJava6(), fail("java latest install failed", 9)); - } - - public static String installJavaLatestOrWarn() { - return alternatives(installJava8(), installJava7(), installJava6(), warn("java latest install failed, entity may subsequently fail")); - } - - /** - * Adds the PPA for OpenJDK for older JDK versions (7 and lower) required by some software (e.g. JBoss) - */ - public static String addOpenJDKPPK(){ - return chainGroup( - sudo("sudo add-apt-repository -y ppa:openjdk-r/ppa"), - sudo("sudo apt-get update")); - } - - /** - * Returns a command which upgrades NSS on Yum based machines - Addresses https://issues.apache.org/jira/browse/BROOKLYN-320 - * @return command - */ - public static String upgradeNSS(){ - return chainGroup( - "which yum", - sudo("yum -y upgrade nss")); - } - - /** cats the given text to the given command, using bash << multi-line input syntax */ - public static String pipeTextTo(String text, String command) { - return "cat << EOL_BROOKLYN | "+command+"\n" - +text - +"\n"+"EOL_BROOKLYN\n"; - } - - public static String pipeTextToFile(String text, String filepath) { - return "cat > \"" + filepath + "\" << EOF_BROOKLYN\n" - + text + "\n" - + "EOF_BROOKLYN\n"; - } - - public static String prependToEtcHosts(String ip, String... hostnames) { - String tempFileId = "bak"+Identifiers.makeRandomId(4); - return sudo(String.format("sed -i."+tempFileId+" -e '1i\\\n%s %s' /etc/hosts", ip, Joiner.on(" ").join(hostnames))); - } - - public static String appendToEtcHosts(String ip, String... hostnames) { - // Using sed rather than `echo ... >> /etc/hosts` because when embedded inside sudo, - // the redirect doesn't get executed by sudo. - String tempFileId = "bak"+Identifiers.makeRandomId(4); - return sudo(String.format("sed -i."+tempFileId+" -e '$a\\\n%s %s' /etc/hosts", ip, Joiner.on(" ").join(hostnames))); - } - - /** - * Sets the hostname, splitting the given hostname if it contains a dot to include the unqualified and fully qualified names. - * - * @see {@link #setHostname(String, String)} - */ - @Beta - public static List<String> setHostname(String newHostname) { - // See http://www.dns-sd.org/trailingdotsindomainnames.html. - // If we are given "abcd." then let's pass that as-is to setHostname("abcd.", null) - - if (newHostname.indexOf(".") > 0) { - String hostPart = newHostname.substring(0, newHostname.indexOf(".")); - String domainPart = newHostname.substring(hostPart.length()+1); - return setHostname(hostPart, domainPart); - } else { - return setHostname(newHostname, null); - } - } - - /** - * Sets the hostname to {@code hostPart + "." + domainPart}, or if domainPart is null/empty then {code hostPart}. - * - * @param hostPart - * @param domainPart - * @return - */ - @Beta - public static List<String> setHostname(String hostPart, String domainPart) { - // See: - // - http://www.rackspace.com/knowledge_center/article/centos-hostname-change - // - https://wiki.debian.org/HowTo/ChangeHostname - // - http://askubuntu.com/questions/9540/how-do-i-change-the-computer-name - // - // We prepend in /etc/hosts, to ensure the right fqn appears first. - // e.g. comment in http://askubuntu.com/questions/158957/how-to-set-the-fully-qualified-domain-name-in-12-04 - // says "It's important to note that the first domain in /etc/hosts should be your FQDN. " - // - // TODO Should we run `sudo service hostname restart` or `sudo /etc/init.d/hostname restart`? - // I don't think we need to because we've run `sudo hostname <newname>` - // - // TODO What if /etc/sysconfig/network doesn't have a line for HOSTNAME=...? - // - // TODO What about hostPart ending in "." - see http://www.dns-sd.org/trailingdotsindomainnames.html - // for what that means in DNS. However, hostname is not the same as the DNS name (hostnames - // predate the invention of DNS! - although frequently the DNS name has the same first portion - // as the hostname) so the link you gave is not relevant. However despite searching Google and - // man pages I [Ricard] am unable to find a reference which clearly states what characters are - // relevant in a hostname. I think it's safest to assume that the hostname is just [a-z,0-9,-] - // and no dots at all. - - checkNotNull(hostPart, "hostPart"); - checkArgument(!hostPart.contains("."), "hostPart '%s' must not contain '.'", hostPart); - - String tempFileId = "bak"+Identifiers.makeRandomId(4); - - List<String> allhostnames = Lists.newArrayList(); - String fqdn = hostPart; - if (Strings.isNonBlank(domainPart)) { - fqdn = hostPart+"."+domainPart; - allhostnames.add(fqdn); - } - allhostnames.add(hostPart); - allhostnames.add("localhost"); - - return ImmutableList.of( - sudo("sed -i."+tempFileId+" -e 's/^127.0.0.1/# Replaced by Brooklyn\\\n#127.0.0.1/' /etc/hosts"), - prependToEtcHosts("127.0.0.1", allhostnames.toArray(new String[allhostnames.size()])), - ifFileExistsElse0("/etc/sysconfig/network", sudo("sed -i."+tempFileId+" -e 's/^HOSTNAME=.*$/HOSTNAME="+hostPart+"/' /etc/sysconfig/network")), - ifFileExistsElse0("/etc/hostname", sudo("sed -i."+tempFileId+" -e 's/^[a-zA-Z_0-9].*$/"+hostPart+"/' /etc/hostname")), - sudo("hostname "+hostPart)); - } + private static final BashCommandsConfigurable instance = BashCommandsConfigurable.newInstance(); + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static final String INSTALL_TAR = instance.INSTALL_TAR; + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static final String INSTALL_CURL = instance.INSTALL_CURL; + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static final String INSTALL_WGET = instance.INSTALL_WGET; + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static final String INSTALL_ZIP = instance.INSTALL_ZIP; + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static final String INSTALL_UNZIP = instance.INSTALL_UNZIP; + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static final String INSTALL_SYSSTAT = instance.INSTALL_SYSSTAT; + + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String installExecutable(Map<?,?> flags, String executable) { return instance.installExecutable(flags, executable); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String installExecutable(String executable) { return instance.installExecutable(executable); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String quiet(String command) { return instance.quiet(command); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String ok(String command) { return instance.ok(command); } + + public static String sudo(String command) { return instance.sudo(command); } + + public static String authSudo(String command, String password) { return instance.authSudo(command, password); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String sudoAsUser(String user, String command) { return instance.sudoAsUser(user, command); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String addSbinPathCommand() { return instance.addSbinPathCommand(); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String sbinPath() { return instance.sbinPath(); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String executeCommandThenAsUserTeeOutputToFile(String commandWhoseOutputToWrite, String user, String file) { return instance.executeCommandThenAsUserTeeOutputToFile(commandWhoseOutputToWrite, user, file); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String dontRequireTtyForSudo() { return instance.dontRequireTtyForSudo(); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String generateKeyInDotSshIdRsaIfNotThere() { return instance.generateKeyInDotSshIdRsaIfNotThere(); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String ifFileExistsElse0(String path, String command) { return instance.ifFileExistsElse0(path, command); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String ifFileExistsElse1(String path, String command) { return instance.ifFileExistsElse1(path, command); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String ifExecutableElse0(String executable, String command) { return instance.ifExecutableElse0(executable, command); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String ifExecutableElse1(String executable, String command) { return instance.ifExecutableElse1(executable, command); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String ifNotExecutable(String command, String statement) { return instance.ifNotExecutable(command, statement); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String onlyIfExecutableMissing(String executable, String command) { return instance.onlyIfExecutableMissing(executable, command); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String ifExecutableElse(String command, String ifNotExist, String ifExist) { return instance.ifExecutableElse(command, ifNotExist, ifExist); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String ifExecutableDoesNotExistElse(String command, String ifNotExist, String ifExist) { return instance.ifExecutableDoesNotExistElse(command, ifNotExist, ifExist); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static ImmutableList<String> ifExecutableElse(String command, List<String> ifNotExist, List<String> ifExist) { return instance.ifExecutableElse(command, ifNotExist, ifExist); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static ImmutableList<String> ifExecutableDoesNotExistElse(String command, List<String> ifNotExist, List<String> ifExist) { return instance.ifExecutableDoesNotExistElse(command, ifNotExist, ifExist); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String chain(Collection<String> commands) { return instance.chain(commands); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String chain(String ...commands) { return instance.chain(commands); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String chainGroup(Collection<String> commands) { return instance.chainGroup(commands); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String chainGroup(String ...commands) { return instance.chainGroup(commands); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String chainSubshell(Collection<String> commands) { return instance.chainSubshell(commands); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String chainSubshell(String ...commands) { return instance.chainSubshell(commands); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String alternatives(Collection<String> commands) { return instance.alternatives(commands); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String alternatives(String ...commands) { return instance.alternatives(commands); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String alternativesGroup(Collection<String> commands) { return instance.alternativesGroup(commands); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String alternativesGroup(String ...commands) { return instance.alternativesGroup(commands); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String alternativesSubshell(Collection<String> commands) { return instance.alternativesSubshell(commands); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String alternativesSubshell(String ...commands) { return instance.alternativesSubshell(commands); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String formatIfNotNull(String pattern, Object arg) { return instance.formatIfNotNull(pattern, arg); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String installPackage(String packageDefaultName) { return instance.installPackage(packageDefaultName); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String installPackage(Map<?,?> flags, String packageDefaultName) { return instance.installPackage(flags, packageDefaultName); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String installPackageOrFail(Map<?,?> flags, String packageDefaultName) { return instance.installPackageOrFail(flags, packageDefaultName); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String installPackageOr(Map<?,?> flags, String packageDefaultName, String optionalCommandToRunIfNone) { return instance.installPackageOr(flags, packageDefaultName, optionalCommandToRunIfNone); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String warn(String message) { return instance.warn(message); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String fail(String message, int code) { return instance.fail(message, code); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String require(String command, String failureMessage, int exitCode) { return instance.require(command, failureMessage, exitCode); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String require(String command, String failureMessage) { return instance.require(command, failureMessage); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String requireTest(String test, String failureMessage, int exitCode) { return instance.requireTest(test, failureMessage, exitCode); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String requireTest(String test, String failureMessage) { return instance.requireTest(test, failureMessage); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String requireFile(String file) { return instance.requireFile(file); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String requireExecutable(String command) { return instance.requireExecutable(command); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String waitForFileContents(String file, String desiredContent, Duration timeout, boolean failOnTimeout) { return instance.waitForFileContents(file, desiredContent, timeout, failOnTimeout); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String waitForFileExists(String file, Duration timeout, boolean failOnTimeout) { return instance.waitForFileExists(file, timeout, failOnTimeout); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String waitForPortFree(int port, Duration timeout, boolean failOnTimeout) { return instance.waitForPortFree(port, timeout, failOnTimeout); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String unzip(String file, String targetDir) { return instance.unzip(file, targetDir); } + + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static List<String> commandsToDownloadUrlsAs(List<String> urls, String saveAs) { return instance.commandsToDownloadUrlsAs(urls, saveAs); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static List<String> commandsToDownloadUrlsAsWithMinimumTlsVersion(List<String> urls, String saveAs, String tlsVersion) { return instance.commandsToDownloadUrlsAsWithMinimumTlsVersion(urls, saveAs, tlsVersion); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String commandToDownloadUrlsAs(List<String> urls, String saveAs) { return instance.commandToDownloadUrlsAs(urls, saveAs); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String commandToDownloadUrlAs(String url, String saveAs) { return instance.commandToDownloadUrlAs(url, saveAs); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String downloadToStdout(List<String> urls) { return instance.downloadToStdout(urls); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String downloadToStdout(String ...urls) { return instance.downloadToStdout(urls); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String simpleDownloadUrlAs(List<String> urls, String saveAs) { return instance.simpleDownloadUrlAs(urls, saveAs); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String simpleDownloadUrlAs(List<String> urls, String saveAs, String tlsVersion) { return instance.simpleDownloadUrlAs(urls, saveAs, tlsVersion); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String simpleDownloadUrlAs(List<String> urls, String user, String password, String saveAs, String tlsVersion) { return instance.simpleDownloadUrlAs(urls, user, password, saveAs, tlsVersion); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String installJava(int version) { return instance.installJava(version); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String installJava6() { return instance.installJava6(); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String installJava7() { return instance.installJava7(); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String installJava8() { return instance.installJava8(); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String installJava6IfPossible() { return instance.installJava6IfPossible(); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String installJava7IfPossible() { return instance.installJava7IfPossible(); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String installJava8IfPossible() { return instance.installJava8IfPossible(); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String installJava6OrFail() { return instance.installJava6OrFail(); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String installJava7OrFail() { return instance.installJava7OrFail(); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String installJava7Or6OrFail() { return instance.installJava7Or6OrFail(); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String installJavaLatestOrFail() { return instance.installJavaLatestOrFail(); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String installJavaLatestOrWarn() { return instance.installJavaLatestOrWarn(); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String addOpenJDKPPK() { return instance.addOpenJDKPPK(); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String upgradeNSS() { return instance.upgradeNSS(); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String pipeTextTo(String text, String command) { return instance.pipeTextTo(text, command); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String pipeTextToFile(String text, String filepath) { return instance.pipeTextToFile(text, filepath); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String prependToEtcHosts(String ip, String... hostnames) { return instance.prependToEtcHosts(ip, hostnames); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static String appendToEtcHosts(String ip, String... hostnames) { return instance.appendToEtcHosts(ip, hostnames); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static List<String> setHostname(String newHostname) { return instance.setHostname(newHostname); } + + @Deprecated /** @deprecated since 1.1 use {@link BashCommandsConfigurable} */ + public static List<String> setHostname(String hostPart, String domainPart) { return instance.setHostname(hostPart, domainPart); } + } diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/ssh/BashCommands.java b/utils/common/src/main/java/org/apache/brooklyn/util/ssh/BashCommandsConfigurable.java similarity index 82% copy from utils/common/src/main/java/org/apache/brooklyn/util/ssh/BashCommands.java copy to utils/common/src/main/java/org/apache/brooklyn/util/ssh/BashCommandsConfigurable.java index d60c9a9a35..111282f16b 100644 --- a/utils/common/src/main/java/org/apache/brooklyn/util/ssh/BashCommands.java +++ b/utils/common/src/main/java/org/apache/brooklyn/util/ssh/BashCommandsConfigurable.java @@ -18,31 +18,38 @@ */ package org.apache.brooklyn.util.ssh; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; -import static java.lang.String.format; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import org.apache.brooklyn.util.collections.MutableMap; -import org.apache.brooklyn.util.text.Identifiers; -import org.apache.brooklyn.util.text.Strings; -import org.apache.brooklyn.util.text.StringEscapes.BashStringEscapes; -import org.apache.brooklyn.util.time.Duration; - import com.google.common.annotations.Beta; import com.google.common.base.Joiner; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; +import org.apache.brooklyn.util.collections.MutableMap; +import org.apache.brooklyn.util.text.Identifiers; +import org.apache.brooklyn.util.text.StringEscapes.BashStringEscapes; +import org.apache.brooklyn.util.text.Strings; +import org.apache.brooklyn.util.time.Duration; + +import java.util.*; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static java.lang.String.format; -public class BashCommands { +public class BashCommandsConfigurable { + + public static BashCommandsConfigurable newInstance() { + return new BashCommandsConfigurable(); + } + + private boolean ignoreCerts = true; + + public BashCommandsConfigurable withIgnoreCerts(Boolean ignoreCerts) { + if (ignoreCerts!=null) this.ignoreCerts = ignoreCerts; + return this; + } + + public boolean isIgnoreCerts() { return this.ignoreCerts; } /** * Returns a string for checking whether the given executable is available, @@ -50,25 +57,25 @@ public class BashCommands { * <p/> * Uses {@link #installPackage} and accepts the same flags e.g. for apt, yum, rpm. */ - public static String installExecutable(Map<?,?> flags, String executable) { + public String installExecutable(Map<?,?> flags, String executable) { return onlyIfExecutableMissing(executable, installPackage(flags, executable)); } - public static String installExecutable(String executable) { + public String installExecutable(String executable) { return installExecutable(MutableMap.of(), executable); } /** * Returns a command with all output redirected to /dev/null */ - public static String quiet(String command) { + public String quiet(String command) { return format("(%s > /dev/null 2>&1)", command); } /** * Returns a command that always exits successfully */ - public static String ok(String command) { + public String ok(String command) { return String.format("(%s || true)", command); } @@ -90,7 +97,7 @@ public class BashCommands { * <p/> * If null is supplied, it is returned (sometimes used to indicate no command desired). */ - public static String sudo(String command) { + public String sudo(String command) { if (command==null) return null; if (command.startsWith("( ") || command.endsWith(" &")) return sudoNew(command); @@ -98,7 +105,7 @@ public class BashCommands { return sudoOld(command); } - public static String authSudo(String command, String password) { + public String authSudo(String command, String password) { checkNotNull(password, "password must not be null"); if (command==null) return null; if (command.startsWith("( ") || command.endsWith(" &")) { @@ -132,7 +139,7 @@ public class BashCommands { * @deprecated since 0.7.0 semantics of this are fiddly, e.g. whether user gets their environment */ @Deprecated @Beta - public static String sudoAsUser(String user, String command) { + public String sudoAsUser(String user, String command) { return sudoAsUserOld(user, command); } @@ -149,17 +156,17 @@ public class BashCommands { // return "{ sudo -n -S -i -u "+user+" -- "+BashStringEscapes.wrapBash(command)+" ; }"; // } - public static String addSbinPathCommand() { + public String addSbinPathCommand() { return "export PATH=" + sbinPath(); } - public static String sbinPath() { + public String sbinPath() { return "$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"; } /** executes a command, then as user tees the output to the given file. * useful e.g. for appending to a file which is only writable by root or a priveleged user. */ - public static String executeCommandThenAsUserTeeOutputToFile(String commandWhoseOutputToWrite, String user, String file) { + public String executeCommandThenAsUserTeeOutputToFile(String commandWhoseOutputToWrite, String user, String file) { return format("{ %s | sudo -E -n -u %s -s -- tee -a %s ; }", commandWhoseOutputToWrite, user, file); } @@ -172,12 +179,12 @@ public class BashCommands { * will try to detect the changes and do nothing. * <p> * This command must be run with allocatePTY set as a flag to ssh. - * See {@link SshTasks#dontRequireTtyForSudo(SshMachineLocation, OnFailingTask)} which sets that up. + * See SshTasks dontRequireTtyForSudo(SshMachineLocation, OnFailingTask) which sets that up. * <p> * Having a TTY for sudo seems like another case of imaginary security which is just irritating. * Like water restrictions at airport security. */ - public static String dontRequireTtyForSudo() { + public String dontRequireTtyForSudo() { String sudoersFileName = "/etc/sudoers"; String tmpSuffix = Identifiers.makeRandomLowercaseId(6); // Avoid clobbering @@ -193,7 +200,7 @@ public class BashCommands { } /** generates ~/.ssh/id_rsa if that file does not exist */ - public static String generateKeyInDotSshIdRsaIfNotThere() { + public String generateKeyInDotSshIdRsaIfNotThere() { return "[ -f ~/.ssh/id_rsa ] || ( mkdir -p ~/.ssh ; chmod 700 ~/.ssh ; ssh-keygen -t rsa -N '' -f ~/.ssh/id_rsa )"; } @@ -206,14 +213,14 @@ public class BashCommands { * Executed as { { not-file-exists && ok ; } || command ; } for portability. * ("if [ ... ] ; then xxx ; else xxx ; fi" syntax is not quite as portable, I seem to recall (not sure, Alex Aug 2013).) */ - public static String ifFileExistsElse0(String path, String command) { + public String ifFileExistsElse0(String path, String command) { return alternativesGroup( chainGroup(format("test ! -e %s", path), "true"), command); } /** as {@link #ifFileExistsElse0(String, String)} but returns non-zero if the test fails (also returns non-zero if the command fails, * so you can't tell the difference :( -- we need if ; then ; else ; fi semantics for that I think, but not sure how portable that is) */ - public static String ifFileExistsElse1(String path, String command) { + public String ifFileExistsElse1(String path, String command) { return chainGroup(format("test -e %s", path), command); } @@ -222,14 +229,14 @@ public class BashCommands { * if the command runs and fails that exit is preserved (but if the executable is not on the path exit code is zero). * @see #ifFileExistsElse0(String, String) for implementation discussion, using <code>{ { test -z `which executable` && true ; } || command ; } */ - public static String ifExecutableElse0(String executable, String command) { + public String ifExecutableElse0(String executable, String command) { return alternativesGroup( chainGroup(format("test -z `which %s`", executable), "true"), command); } /** as {@link #ifExecutableElse0(String, String)} but returns 1 if the test fails (also returns non-zero if the command fails) */ - public static String ifExecutableElse1(String executable, String command) { + public String ifExecutableElse1(String executable, String command) { return chainGroup(format("which %s", executable), command); } @@ -241,7 +248,7 @@ public class BashCommands { * @param statement * @return command */ - public static String ifNotExecutable(String command, String statement) { + public String ifNotExecutable(String command, String statement) { return String.format("{ { test ! -z `which %s`; } || { %s; } }", command, statement); } @@ -250,7 +257,7 @@ public class BashCommands { * if the command runs and fails that exit is preserved (but if the executable is not on the path exit code is zero). * @see #ifFileExistsElse0(String, String) for implementation discussion, using <code>{ { test -z `which executable` && true ; } || command ; } */ - public static String onlyIfExecutableMissing(String executable, String command) { + public String onlyIfExecutableMissing(String executable, String command) { return alternativesGroup(format("which %s", executable), command); } @@ -258,11 +265,11 @@ public class BashCommands { * @deprecated As of release 0.10.0, replaced by {@link #ifExecutableDoesNotExistElse(String, String, String)} */ @Deprecated - public static String ifExecutableElse(String command, String ifNotExist, String ifExist) { + public String ifExecutableElse(String command, String ifNotExist, String ifExist) { return ifExecutableDoesNotExistElse(command, ifNotExist, ifExist); } - public static String ifExecutableDoesNotExistElse(String command, String ifNotExist, String ifExist) { + public String ifExecutableDoesNotExistElse(String command, String ifNotExist, String ifExist) { return com.google.common.base.Joiner.on('\n').join( ifExecutableDoesNotExistElse(command, ImmutableList.<String>of(ifNotExist), ImmutableList.<String>of(ifExist))); } @@ -271,11 +278,11 @@ public class BashCommands { * @deprecated As of release 0.10.0, replaced by {@link #ifExecutableDoesNotExistElse(String, List, List)} */ @Deprecated - public static ImmutableList<String> ifExecutableElse(String command, List<String> ifNotExist, List<String> ifExist) { + public ImmutableList<String> ifExecutableElse(String command, List<String> ifNotExist, List<String> ifExist) { return ifExecutableDoesNotExistElse(command, ifNotExist, ifExist); } - public static ImmutableList<String> ifExecutableDoesNotExistElse(String command, List<String> ifNotExist, List<String> ifExist) { + public ImmutableList<String> ifExecutableDoesNotExistElse(String command, List<String> ifNotExist, List<String> ifExist) { return ImmutableList.<String>builder() .add(String.format("if test -z `which %s`; then", command)) .addAll(ifNotExist) @@ -290,37 +297,37 @@ public class BashCommands { * This currently runs as a subshell (so exits are swallowed) but behaviour may be changed imminently. * (Use {@link #chainGroup(Collection)} or {@link #chainSubshell(Collection)} to be clear.) */ - public static String chain(Collection<String> commands) { + public String chain(Collection<String> commands) { return "( " + Strings.join(commands, " && ") + " )"; } /** Convenience for {@link #chain(Collection)} */ - public static String chain(String ...commands) { + public String chain(String ...commands) { return "( " + Strings.join(commands, " && ") + " )"; } /** As {@link #chain(Collection)}, but explicitly using { } grouping characters * to ensure exits are propagated. */ - public static String chainGroup(Collection<String> commands) { + public String chainGroup(Collection<String> commands) { // spaces required around curly braces return "{ " + Strings.join(commands, " && ") + " ; }"; } /** As {@link #chainGroup(Collection)} */ - public static String chainGroup(String ...commands) { + public String chainGroup(String ...commands) { return "{ " + Strings.join(commands, " && ") + " ; }"; } /** As {@link #chain(Collection)}, but explicitly using ( ) grouping characters * to ensure exits are caught. */ - public static String chainSubshell(Collection<String> commands) { + public String chainSubshell(Collection<String> commands) { // the spaces are not required, but it might be possible that a (( expr )) is interpreted differently // (won't hurt to have the spaces in any case!) return "( " + Strings.join(commands, " && ") + " )"; } /** As {@link #chainSubshell(Collection)} */ - public static String chainSubshell(String ...commands) { + public String chainSubshell(String ...commands) { return "( " + Strings.join(commands, " && ") + " )"; } @@ -329,47 +336,47 @@ public class BashCommands { * This currently runs as a subshell (so exits are swallowed) but behaviour may be changed imminently. * (Use {@link #alternativesGroup(Collection)} or {@link #alternativesSubshell(Collection)} to be clear.) */ - public static String alternatives(Collection<String> commands) { + public String alternatives(Collection<String> commands) { return "( " + Strings.join(commands, " || ") + " )"; } /** As {@link #alternatives(Collection)} */ - public static String alternatives(String ...commands) { + public String alternatives(String ...commands) { return "( " + Strings.join(commands, " || ") + " )"; } /** As {@link #alternatives(Collection)}, but explicitly using { } grouping characters * to ensure exits are propagated. */ - public static String alternativesGroup(Collection<String> commands) { + public String alternativesGroup(Collection<String> commands) { // spaces required around curly braces return "{ " + Strings.join(commands, " || ") + " ; }"; } /** As {@link #alternativesGroup(Collection)} */ - public static String alternativesGroup(String ...commands) { + public String alternativesGroup(String ...commands) { return "{ " + Strings.join(commands, " || ") + " ; }"; } /** As {@link #alternatives(Collection)}, but explicitly using ( ) grouping characters * to ensure exits are caught. */ - public static String alternativesSubshell(Collection<String> commands) { + public String alternativesSubshell(Collection<String> commands) { // the spaces are not required, but it might be possible that a (( expr )) is interpreted differently // (won't hurt to have the spaces in any case!) return "( " + Strings.join(commands, " || ") + " )"; } /** As {@link #alternativesSubshell(Collection)} */ - public static String alternativesSubshell(String ...commands) { + public String alternativesSubshell(String ...commands) { return "( " + Strings.join(commands, " || ") + " )"; } /** returns the pattern formatted with the given arg if the arg is not null, otherwise returns null */ - public static String formatIfNotNull(String pattern, Object arg) { + public String formatIfNotNull(String pattern, Object arg) { if (arg==null) return null; return format(pattern, arg); } - public static String installPackage(String packageDefaultName) { + public String installPackage(String packageDefaultName) { return installPackage(MutableMap.of(), packageDefaultName); } /** @@ -387,17 +394,17 @@ public class BashCommands { * installPackage(ImmutableMap.of("onlyifmissing", "curl"), "curl"); * </pre> */ - public static String installPackage(Map<?,?> flags, String packageDefaultName) { + public String installPackage(Map<?,?> flags, String packageDefaultName) { return installPackageOr(flags, packageDefaultName, null); } - public static String installPackageOrFail(Map<?,?> flags, String packageDefaultName) { + public String installPackageOrFail(Map<?,?> flags, String packageDefaultName) { return installPackageOr(flags, packageDefaultName, "exit 9"); } - public static String installPackageOr(Map<?,?> flags, String packageDefaultName, String optionalCommandToRunIfNone) { + public String installPackageOr(Map<?,?> flags, String packageDefaultName, String optionalCommandToRunIfNone) { String ifMissing = (String) flags.get("onlyifmissing"); - String zypperInstall = formatIfNotNull("zypper --non-interactive --no-gpg-checks install %s", getFlag(flags, "zypper", packageDefaultName)); + String zypperInstall = formatIfNotNull("zypper --non-interactive"+(isIgnoreCerts() ? " --no-gpg-checks" : "")+" install %s", getFlag(flags, "zypper", packageDefaultName)); String aptInstall = formatIfNotNull("apt-get install -y --allow-unauthenticated %s", getFlag(flags, "apt", packageDefaultName)); - String yumInstall = formatIfNotNull("yum -y --nogpgcheck install %s", getFlag(flags, "yum", packageDefaultName)); + String yumInstall = formatIfNotNull("yum -y"+(isIgnoreCerts() ? " --nogpgcheck" : "")+" install %s", getFlag(flags, "yum", packageDefaultName)); String brewInstall = formatIfNotNull("brew install %s", getFlag(flags, "brew", packageDefaultName)); String portInstall = formatIfNotNull("port install %s", getFlag(flags, "port", packageDefaultName)); @@ -442,48 +449,48 @@ public class BashCommands { return alternatives(commands); } - public static String warn(String message) { + public String warn(String message) { return "( echo "+BashStringEscapes.wrapBash(message)+" | tee /dev/stderr )"; } /** returns a command which logs a message to stdout and stderr then exits with the given error code */ - public static String fail(String message, int code) { + public String fail(String message, int code) { return chainGroup(warn(message), "exit "+code); } /** requires the command to have a non-zero exit code; e.g. * <code>require("which foo", "Command foo must be found", 1)</code> */ - public static String require(String command, String failureMessage, int exitCode) { + public String require(String command, String failureMessage, int exitCode) { return alternativesGroup(command, fail(failureMessage, exitCode)); } /** as {@link #require(String, String, int)} but returning the original exit code */ - public static String require(String command, String failureMessage) { + public String require(String command, String failureMessage) { return alternativesGroup(command, chainGroup("EXIT_CODE=$?", warn(failureMessage), "exit $EXIT_CODE")); } /** requires the test to pass, as valid bash `test` arguments; e.g. * <code>requireTest("-f /etc/hosts", "Hosts file must exist", 1)</code> */ - public static String requireTest(String test, String failureMessage, int exitCode) { + public String requireTest(String test, String failureMessage, int exitCode) { return require("test "+test, failureMessage, exitCode); } /** as {@link #requireTest(String, String, int)} but returning the original exit code */ - public static String requireTest(String test, String failureMessage) { + public String requireTest(String test, String failureMessage) { return require("test "+test, failureMessage); } /** fails with nice error if the given file does not exist */ - public static String requireFile(String file) { + public String requireFile(String file) { return requireTest("-f "+BashStringEscapes.wrapBash(file), "The required file \""+file+"\" does not exist"); } /** fails with nice error if the given file does not exist */ - public static String requireExecutable(String command) { + public String requireExecutable(String command) { return require("which "+BashStringEscapes.wrapBash(command), "The required executable \""+command+"\" does not exist"); } - public static String waitForFileContents(String file, String desiredContent, Duration timeout, boolean failOnTimeout) { + public String waitForFileContents(String file, String desiredContent, Duration timeout, boolean failOnTimeout) { long secs = Math.max(timeout.toSeconds(), 1); List<String> commands = ImmutableList.of( @@ -502,7 +509,7 @@ public class BashCommands { return Joiner.on("\n").join(commands); } - public static String waitForFileExists(String file, Duration timeout, boolean failOnTimeout) { + public String waitForFileExists(String file, Duration timeout, boolean failOnTimeout) { long secs = Math.max(timeout.toSeconds(), 1); List<String> commands = ImmutableList.of( @@ -519,7 +526,7 @@ public class BashCommands { return Joiner.on("\n").join(commands); } - public static String waitForPortFree(int port, Duration timeout, boolean failOnTimeout) { + public String waitForPortFree(int port, Duration timeout, boolean failOnTimeout) { long secs = Math.max(timeout.toSeconds(), 1); // TODO How platform-dependent are the args + output format of netstat? @@ -533,7 +540,7 @@ public class BashCommands { List<String> commands = ImmutableList.of( "for i in {1.."+secs+"}; do", - " "+BashCommands.requireExecutable("netstat"), + " "+ requireExecutable("netstat"), " "+alternativesGroup( chainGroup("which awk", "AWK_EXEC=awk"), chainGroup("which gawk", "AWK_EXEC=gawk"), @@ -551,22 +558,22 @@ public class BashCommands { return Joiner.on("\n").join(commands); } - public static String unzip(String file, String targetDir) { + public String unzip(String file, String targetDir) { return "unzip " + file + (Strings.isNonBlank(targetDir) ? " -d "+targetDir : ""); } - public static final String INSTALL_TAR = installExecutable("tar"); - public static final String INSTALL_CURL = installExecutable("curl"); - public static final String INSTALL_WGET = installExecutable("wget"); - public static final String INSTALL_ZIP = installExecutable("zip"); - public static final String INSTALL_UNZIP = alternatives(installExecutable("unzip"), installExecutable("zip")); - public static final String INSTALL_SYSSTAT = installPackage(ImmutableMap.of("onlyifmissing", "iostat"), "sysstat"); + public final String INSTALL_TAR = installExecutable("tar"); + public final String INSTALL_CURL = installExecutable("curl"); + public final String INSTALL_WGET = installExecutable("wget"); + public final String INSTALL_ZIP = installExecutable("zip"); + public final String INSTALL_UNZIP = alternatives(installExecutable("unzip"), installExecutable("zip")); + public final String INSTALL_SYSSTAT = installPackage(ImmutableMap.of("onlyifmissing", "iostat"), "sysstat"); /** * Returns commands to download the URL, saving as the given file. Will try each URL in turn until one is successful * (see `curl -f` documentation). */ - public static List<String> commandsToDownloadUrlsAs(List<String> urls, String saveAs) { + public List<String> commandsToDownloadUrlsAs(List<String> urls, String saveAs) { return Arrays.asList(INSTALL_CURL, require(simpleDownloadUrlAs(urls, saveAs), "Could not retrieve "+saveAs+". Tried: " + Joiner.on(", ").join(urls), 9)); } @@ -576,16 +583,16 @@ public class BashCommands { * It allows setting a minimum TLS version to avoid this error: <code> <curl: (35) Peer reports incompatible or unsupported protocol version./code> * (see `curl -f` documentation). */ - public static List<String> commandsToDownloadUrlsAsWithMinimumTlsVersion(List<String> urls, String saveAs, String tlsVersion) { + public List<String> commandsToDownloadUrlsAsWithMinimumTlsVersion(List<String> urls, String saveAs, String tlsVersion) { return Arrays.asList(INSTALL_CURL, require(simpleDownloadUrlAs(urls, saveAs, tlsVersion), "Could not retrieve "+saveAs+". Tried: " + Joiner.on(", ").join(urls), 9)); } - public static String commandToDownloadUrlsAs(List<String> urls, String saveAs) { + public String commandToDownloadUrlsAs(List<String> urls, String saveAs) { return chain(INSTALL_CURL, require(simpleDownloadUrlAs(urls, saveAs), "Could not retrieve "+saveAs+". Tried: " + Joiner.on(", ").join(urls), 9)); } - public static String commandToDownloadUrlAs(String url, String saveAs) { + public String commandToDownloadUrlAs(String url, String saveAs) { return chain(INSTALL_CURL, require(simpleDownloadUrlAs(Arrays.asList(url), saveAs), "Could not retrieve "+saveAs+" from " + url, 9)); } @@ -595,7 +602,7 @@ public class BashCommands { * suitable for redirect by appending " | tar xvf". * Will try each URL in turn until one is successful */ - public static String downloadToStdout(List<String> urls) { + public String downloadToStdout(List<String> urls) { return chain( INSTALL_CURL + " > /dev/null", require(simpleDownloadUrlAs(urls, null), @@ -603,34 +610,34 @@ public class BashCommands { } /** as {@link #downloadToStdout(List)} but varargs for convenience */ - public static String downloadToStdout(String ...urls) { + public String downloadToStdout(String ...urls) { return downloadToStdout(Arrays.asList(urls)); } /** - * Same as {@link simpleDownloadUrlAs(List, String)}, except does not install curl, and does not exit on failure, + * Same as {@link #simpleDownloadUrlAs(List, String)}, except does not install curl, and does not exit on failure, * and if saveAs is null it downloads it so stdout. */ - public static String simpleDownloadUrlAs(List<String> urls, String saveAs) { + public String simpleDownloadUrlAs(List<String> urls, String saveAs) { return simpleDownloadUrlAs(urls, null, null, saveAs, null); } /** - * Same as {@link simpleDownloadUrlAs(List, String, String)}, except does not install curl, and does not exit on failure, + * Same as {@link #simpleDownloadUrlAs(List, String, String)}, except does not install curl, and does not exit on failure, * and if saveAs is null it downloads it so stdout. */ - public static String simpleDownloadUrlAs(List<String> urls, String saveAs, String tlsVersion) { + public String simpleDownloadUrlAs(List<String> urls, String saveAs, String tlsVersion) { return simpleDownloadUrlAs(urls, null, null, saveAs, tlsVersion); } - public static String simpleDownloadUrlAs(List<String> urls, String user, String password, String saveAs, String tlsVersion) { + public String simpleDownloadUrlAs(List<String> urls, String user, String password, String saveAs, String tlsVersion) { if (urls.isEmpty()) throw new IllegalArgumentException("No URLs supplied to download "+saveAs); List<String> commands = new ArrayList<String>(); for (String url : urls) { String command = tlsVersion == null ? - "curl -f -L -k --retry 10 --keepalive-time 30 --speed-time 30 " : - "curl --tlsv" + tlsVersion + " -f -L -k --retry 10 --keepalive-time 30 --speed-time 30 " ; + "curl -f -L"+(isIgnoreCerts() ? " -k" : "")+" --retry 10 --keepalive-time 30 --speed-time 30 " : + "curl --tlsv" + tlsVersion + " -f -L "+(isIgnoreCerts() ? " -k" : "")+" --retry 10 --keepalive-time 30 --speed-time 30 " ; if (user!=null && password!=null) { command = command + format("-u %s:%s ", user, password); } @@ -643,7 +650,7 @@ public class BashCommands { return alternatives(commands); } - private static Object getFlag(Map<?,?> flags, String flagName, Object defaultValue) { + private Object getFlag(Map<?,?> flags, String flagName, Object defaultValue) { Object found = flags.get(flagName); return found == null ? defaultValue : found; } @@ -658,7 +665,7 @@ public class BashCommands { * @see #installJava7Or6OrFail() * @see #installJavaLatestOrFail() */ - public static String installJava(int version) { + public String installJava(int version) { Preconditions.checkArgument(version == 6 || version == 7 || version == 8, "Supported Java versions are 6, 7, or 8"); List<String> commands = new LinkedList<String>(); commands.add(ok(addOpenJDKPPK())); @@ -674,47 +681,47 @@ public class BashCommands { return chainGroup(commands); } - public static String installJava6() { + public String installJava6() { return installJava(6); } - public static String installJava7() { + public String installJava7() { return installJava(7); } - public static String installJava8() { + public String installJava8() { return installJava(8); } - public static String installJava6IfPossible() { + public String installJava6IfPossible() { return ok(installJava6()); } - public static String installJava7IfPossible() { + public String installJava7IfPossible() { return ok(installJava7()); } - public static String installJava8IfPossible() { + public String installJava8IfPossible() { return ok(installJava8()); } - public static String installJava6OrFail() { + public String installJava6OrFail() { return alternatives(installJava6(), fail("java 6 install failed", 9)); } - public static String installJava7OrFail() { + public String installJava7OrFail() { return alternatives(installJava7(), fail("java 7 install failed", 9)); } - public static String installJava7Or6OrFail() { + public String installJava7Or6OrFail() { return alternatives(installJava7(), installJava6(), fail("java install failed", 9)); } - public static String installJavaLatestOrFail() { + public String installJavaLatestOrFail() { return alternatives(installJava8(), installJava7(), installJava6(), fail("java latest install failed", 9)); } - public static String installJavaLatestOrWarn() { + public String installJavaLatestOrWarn() { return alternatives(installJava8(), installJava7(), installJava6(), warn("java latest install failed, entity may subsequently fail")); } /** * Adds the PPA for OpenJDK for older JDK versions (7 and lower) required by some software (e.g. JBoss) */ - public static String addOpenJDKPPK(){ + public String addOpenJDKPPK(){ return chainGroup( sudo("sudo add-apt-repository -y ppa:openjdk-r/ppa"), sudo("sudo apt-get update")); @@ -724,31 +731,31 @@ public class BashCommands { * Returns a command which upgrades NSS on Yum based machines - Addresses https://issues.apache.org/jira/browse/BROOKLYN-320 * @return command */ - public static String upgradeNSS(){ + public String upgradeNSS(){ return chainGroup( "which yum", sudo("yum -y upgrade nss")); } /** cats the given text to the given command, using bash << multi-line input syntax */ - public static String pipeTextTo(String text, String command) { + public String pipeTextTo(String text, String command) { return "cat << EOL_BROOKLYN | "+command+"\n" +text +"\n"+"EOL_BROOKLYN\n"; } - public static String pipeTextToFile(String text, String filepath) { + public String pipeTextToFile(String text, String filepath) { return "cat > \"" + filepath + "\" << EOF_BROOKLYN\n" + text + "\n" + "EOF_BROOKLYN\n"; } - public static String prependToEtcHosts(String ip, String... hostnames) { + public String prependToEtcHosts(String ip, String... hostnames) { String tempFileId = "bak"+Identifiers.makeRandomId(4); return sudo(String.format("sed -i."+tempFileId+" -e '1i\\\n%s %s' /etc/hosts", ip, Joiner.on(" ").join(hostnames))); } - public static String appendToEtcHosts(String ip, String... hostnames) { + public String appendToEtcHosts(String ip, String... hostnames) { // Using sed rather than `echo ... >> /etc/hosts` because when embedded inside sudo, // the redirect doesn't get executed by sudo. String tempFileId = "bak"+Identifiers.makeRandomId(4); @@ -761,7 +768,7 @@ public class BashCommands { * @see {@link #setHostname(String, String)} */ @Beta - public static List<String> setHostname(String newHostname) { + public List<String> setHostname(String newHostname) { // See http://www.dns-sd.org/trailingdotsindomainnames.html. // If we are given "abcd." then let's pass that as-is to setHostname("abcd.", null) @@ -782,7 +789,7 @@ public class BashCommands { * @return */ @Beta - public static List<String> setHostname(String hostPart, String domainPart) { + public List<String> setHostname(String hostPart, String domainPart) { // See: // - http://www.rackspace.com/knowledge_center/article/centos-hostname-change // - https://wiki.debian.org/HowTo/ChangeHostname @@ -826,4 +833,5 @@ public class BashCommands { ifFileExistsElse0("/etc/hostname", sudo("sed -i."+tempFileId+" -e 's/^[a-zA-Z_0-9].*$/"+hostPart+"/' /etc/hostname")), sudo("hostname "+hostPart)); } + } diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/ssh/IptablesCommands.java b/utils/common/src/main/java/org/apache/brooklyn/util/ssh/IptablesCommands.java index d50454445a..6f5b42a114 100644 --- a/utils/common/src/main/java/org/apache/brooklyn/util/ssh/IptablesCommands.java +++ b/utils/common/src/main/java/org/apache/brooklyn/util/ssh/IptablesCommands.java @@ -18,14 +18,10 @@ */ package org.apache.brooklyn.util.ssh; -import static org.apache.brooklyn.util.ssh.BashCommands.alternatives; -import static org.apache.brooklyn.util.ssh.BashCommands.chain; -import static org.apache.brooklyn.util.ssh.BashCommands.installPackage; -import static org.apache.brooklyn.util.ssh.BashCommands.sudo; - import com.google.common.annotations.Beta; import com.google.common.base.Optional; +@Deprecated /** @deprecated since 1.1 use {@link IptablesCommandsConfigurable} */ public class IptablesCommands { public enum Chain { @@ -36,91 +32,56 @@ public class IptablesCommands { ACCEPT, REJECT, DROP, LOG } - /** - * @deprecated since 0.7; use {@link org.apache.brooklyn.util.net.Protocol}; kept for persisted state backwards compatibility. - */ - @Deprecated - public enum Protocol { - TCP("tcp"), UDP("udp"), ALL("all"); - - final String protocol; - - private Protocol(String protocol) { - this.protocol = protocol; - } - - @Override - public String toString() { - return protocol; - } - - org.apache.brooklyn.util.net.Protocol convert() { - switch (this) { - case TCP: return org.apache.brooklyn.util.net.Protocol.TCP; - case UDP: return org.apache.brooklyn.util.net.Protocol.UDP; - case ALL: return org.apache.brooklyn.util.net.Protocol.ALL; - default: throw new IllegalStateException("Unexpected protocol "+this); - } - } - } - - @Beta // implementation not portable across distros - public static String iptablesService(String cmd) { - return sudo(alternatives( - BashCommands.ifExecutableElse1("service", "service iptables " + cmd), - "/sbin/service iptables " + cmd)); - } + private static final IptablesCommandsConfigurable instance = new IptablesCommandsConfigurable(BashCommandsConfigurable.newInstance()); @Beta // implementation not portable across distros - public static String iptablesServiceStop() { - return iptablesService("stop"); + public String iptablesServiceStop() { + return instance.iptablesServiceStop(); } @Beta // implementation not portable across distros - public static String iptablesServiceStart() { - return iptablesService("start"); + public String iptablesServiceStart() { + return instance.iptablesServiceStart(); } @Beta // implementation not portable across distros - public static String iptablesServiceRestart() { - return iptablesService("restart"); + public String iptablesServiceRestart() { + return instance.iptablesServiceRestart(); } @Beta // implementation not portable across distros - public static String iptablesServiceStatus() { - return iptablesService("status"); + public String iptablesServiceStatus() { + return instance.iptablesServiceStatus(); } @Beta // implementation not portable across distros - public static String firewalldService(String cmd) { - return sudo(alternatives( - BashCommands.ifExecutableElse1("systemctl", "systemctl " + cmd + " firewalld"), - "/usr/bin/systemctl " + cmd + " firewalld")); + public String firewalldService(String cmd) { + return instance.firewalldService(cmd); } @Beta // implementation not portable across distros - public static String firewalldServiceStop() { - return firewalldService("stop"); + public String firewalldServiceStop() { + return instance.firewalldServiceStop(); } @Beta // implementation not portable across distros - public static String firewalldServiceStart() { - return firewalldService("start"); + public String firewalldServiceStart() { + return instance.firewalldServiceStart(); } @Beta // implementation not portable across distros - public static String firewalldServiceRestart() { - return firewalldService("restart"); + public String firewalldServiceRestart() { + return instance.firewalldServiceRestart(); } @Beta // implementation not portable across distros - public static String firewalldServiceStatus() { - return firewalldService("status"); + public String firewalldServiceStatus() { + return instance.firewalldServiceStatus(); } @Beta // implementation not portable across distros - public static String firewalldServiceIsActive() { - return firewalldService("is-active"); + public String firewalldServiceIsActive() { + return instance.firewalldServiceIsActive(); } /** @@ -129,9 +90,8 @@ public class IptablesCommands { * @return Returns the command that saves iptables rules on file. * */ - public static String saveIptablesRules() { - return alternatives(sudo("service iptables save"), - chain(installPackage("iptables-persistent"), sudo("/etc/init.d/iptables-persistent save"))); + public String saveIptablesRules() { + return instance.saveIptablesRules(); } /** @@ -139,8 +99,8 @@ public class IptablesCommands { * * @return Returns the command that cleans up iptables rules. */ - public static String cleanUpIptablesRules() { - return sudo("/sbin/iptables -F"); + public String cleanUpIptablesRules() { + return instance.cleanUpIptablesRules(); } /** @@ -148,8 +108,8 @@ public class IptablesCommands { * * @return Returns the command that list all the iptables rules. */ - public static String listIptablesRule() { - return sudo("/sbin/iptables -L -v -n"); + public String listIptablesRule() { + return instance.listIptablesRule(); } /** @@ -158,8 +118,8 @@ public class IptablesCommands { * @return Returns the command that inserts a rule on top of the iptables' * rules. */ - public static String insertIptablesRule(Chain chain, org.apache.brooklyn.util.net.Protocol protocol, int port, Policy policy) { - return addIptablesRule("-I", chain, Optional.<String> absent(), protocol, port, policy); + public String insertIptablesRule(IptablesCommandsConfigurable.Chain chain, org.apache.brooklyn.util.net.Protocol protocol, int port, IptablesCommandsConfigurable.Policy policy) { + return instance.insertIptablesRule(chain, protocol, port, policy); } /** @@ -168,8 +128,8 @@ public class IptablesCommands { * @return Returns the command that inserts a rule on top of the iptables' * rules. */ - public static String insertIptablesRule(Chain chain, String networkInterface, org.apache.brooklyn.util.net.Protocol protocol, int port, Policy policy) { - return addIptablesRule("-I", chain, Optional.of(networkInterface), protocol, port, policy); + public String insertIptablesRule(IptablesCommandsConfigurable.Chain chain, String networkInterface, org.apache.brooklyn.util.net.Protocol protocol, int port, IptablesCommandsConfigurable.Policy policy) { + return instance.insertIptablesRule(chain, networkInterface, protocol, port, policy); } /** @@ -177,8 +137,8 @@ public class IptablesCommands { * * @return Returns the command that appends a rule to iptables. */ - public static String appendIptablesRule(Chain chain, org.apache.brooklyn.util.net.Protocol protocol, int port, Policy policy) { - return addIptablesRule("-A", chain, Optional.<String> absent(), protocol, port, policy); + public String appendIptablesRule(IptablesCommandsConfigurable.Chain chain, org.apache.brooklyn.util.net.Protocol protocol, int port, IptablesCommandsConfigurable.Policy policy) { + return instance.appendIptablesRule(chain, protocol, port, policy); } /** @@ -186,8 +146,8 @@ public class IptablesCommands { * * @return Returns the command that appends a rule to iptables. */ - public static String appendIptablesRule(Chain chain, String networkInterface, org.apache.brooklyn.util.net.Protocol protocol, int port, Policy policy) { - return addIptablesRule("-A", chain, Optional.of(networkInterface), protocol, port, policy); + public String appendIptablesRule(IptablesCommandsConfigurable.Chain chain, String networkInterface, org.apache.brooklyn.util.net.Protocol protocol, int port, IptablesCommandsConfigurable.Policy policy) { + return instance.appendIptablesRule(chain, networkInterface, protocol, port, policy); } /** @@ -195,14 +155,8 @@ public class IptablesCommands { * * @return Returns the command that creates a rule for iptables. */ - public static String addIptablesRule(String direction, Chain chain, Optional<String> networkInterface, org.apache.brooklyn.util.net.Protocol protocol, int port, Policy policy) { - String addIptablesRule; - if(networkInterface.isPresent()) { - addIptablesRule = String.format("/sbin/iptables %s %s -i %s -p %s --dport %d -j %s", direction, chain, networkInterface.get(), protocol, port, policy); - } else { - addIptablesRule = String.format("/sbin/iptables %s %s -p %s --dport %d -j %s", direction, chain, protocol, port, policy); - } - return sudo(addIptablesRule); + public String addIptablesRule(String direction, IptablesCommandsConfigurable.Chain chain, Optional<String> networkInterface, org.apache.brooklyn.util.net.Protocol protocol, int port, IptablesCommandsConfigurable.Policy policy) { + return instance.addIptablesRule(direction, chain, networkInterface, protocol, port, policy); } /** @@ -210,24 +164,18 @@ public class IptablesCommands { * * @return Returns the command that adds firewalld direct rule. */ - public static String addFirewalldRule(Chain chain, org.apache.brooklyn.util.net.Protocol protocol, int port, Policy policy) { - return addFirewalldRule(chain, Optional.<String>absent(), protocol, port, policy); + public String addFirewalldRule(IptablesCommandsConfigurable.Chain chain, org.apache.brooklyn.util.net.Protocol protocol, int port, IptablesCommandsConfigurable.Policy policy) { + return instance.addFirewalldRule(chain, protocol, port, policy); } - + /** * Returns the command that adds firewalld direct rule. * * @return Returns the command that adds firewalld direct rule. */ - public static String addFirewalldRule(Chain chain, Optional<String> networkInterface, org.apache.brooklyn.util.net.Protocol protocol, int port, Policy policy) { - String command = new String("/usr/bin/firewall-cmd"); - String commandPermanent = new String("/usr/bin/firewall-cmd --permanent"); - - String interfaceParameter = String.format("%s", networkInterface.isPresent() ? " -i " + networkInterface.get() : ""); - - String commandParameters = String.format(" --direct --add-rule ipv4 filter %s 0 %s -p %s --dport %d -j %s", - chain, interfaceParameter, protocol, port, policy); - - return sudo(chain(command + commandParameters, commandPermanent + commandParameters)); + public String addFirewalldRule(IptablesCommandsConfigurable.Chain chain, Optional<String> networkInterface, org.apache.brooklyn.util.net.Protocol protocol, int port, IptablesCommandsConfigurable.Policy policy) { + + return instance.addFirewalldRule(chain, networkInterface, protocol, port, policy); } + } diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/ssh/IptablesCommands.java b/utils/common/src/main/java/org/apache/brooklyn/util/ssh/IptablesCommandsConfigurable.java similarity index 69% copy from utils/common/src/main/java/org/apache/brooklyn/util/ssh/IptablesCommands.java copy to utils/common/src/main/java/org/apache/brooklyn/util/ssh/IptablesCommandsConfigurable.java index d50454445a..4ddb1a96d6 100644 --- a/utils/common/src/main/java/org/apache/brooklyn/util/ssh/IptablesCommands.java +++ b/utils/common/src/main/java/org/apache/brooklyn/util/ssh/IptablesCommandsConfigurable.java @@ -18,15 +18,10 @@ */ package org.apache.brooklyn.util.ssh; -import static org.apache.brooklyn.util.ssh.BashCommands.alternatives; -import static org.apache.brooklyn.util.ssh.BashCommands.chain; -import static org.apache.brooklyn.util.ssh.BashCommands.installPackage; -import static org.apache.brooklyn.util.ssh.BashCommands.sudo; - import com.google.common.annotations.Beta; import com.google.common.base.Optional; -public class IptablesCommands { +public class IptablesCommandsConfigurable { public enum Chain { INPUT, FORWARD, OUTPUT @@ -36,6 +31,12 @@ public class IptablesCommands { ACCEPT, REJECT, DROP, LOG } + private final BashCommandsConfigurable bash; + + public IptablesCommandsConfigurable(BashCommandsConfigurable bash) { + this.bash = bash; + } + /** * @deprecated since 0.7; use {@link org.apache.brooklyn.util.net.Protocol}; kept for persisted state backwards compatibility. */ @@ -65,61 +66,61 @@ public class IptablesCommands { } @Beta // implementation not portable across distros - public static String iptablesService(String cmd) { - return sudo(alternatives( - BashCommands.ifExecutableElse1("service", "service iptables " + cmd), + public String iptablesService(String cmd) { + return bash.sudo(bash.alternatives( + bash.ifExecutableElse1("service", "service iptables " + cmd), "/sbin/service iptables " + cmd)); } @Beta // implementation not portable across distros - public static String iptablesServiceStop() { + public String iptablesServiceStop() { return iptablesService("stop"); } @Beta // implementation not portable across distros - public static String iptablesServiceStart() { + public String iptablesServiceStart() { return iptablesService("start"); } @Beta // implementation not portable across distros - public static String iptablesServiceRestart() { + public String iptablesServiceRestart() { return iptablesService("restart"); } @Beta // implementation not portable across distros - public static String iptablesServiceStatus() { + public String iptablesServiceStatus() { return iptablesService("status"); } @Beta // implementation not portable across distros - public static String firewalldService(String cmd) { - return sudo(alternatives( - BashCommands.ifExecutableElse1("systemctl", "systemctl " + cmd + " firewalld"), + public String firewalldService(String cmd) { + return bash.sudo(bash.alternatives( + bash.ifExecutableElse1("systemctl", "systemctl " + cmd + " firewalld"), "/usr/bin/systemctl " + cmd + " firewalld")); } @Beta // implementation not portable across distros - public static String firewalldServiceStop() { + public String firewalldServiceStop() { return firewalldService("stop"); } @Beta // implementation not portable across distros - public static String firewalldServiceStart() { + public String firewalldServiceStart() { return firewalldService("start"); } @Beta // implementation not portable across distros - public static String firewalldServiceRestart() { + public String firewalldServiceRestart() { return firewalldService("restart"); } @Beta // implementation not portable across distros - public static String firewalldServiceStatus() { + public String firewalldServiceStatus() { return firewalldService("status"); } @Beta // implementation not portable across distros - public static String firewalldServiceIsActive() { + public String firewalldServiceIsActive() { return firewalldService("is-active"); } @@ -129,9 +130,9 @@ public class IptablesCommands { * @return Returns the command that saves iptables rules on file. * */ - public static String saveIptablesRules() { - return alternatives(sudo("service iptables save"), - chain(installPackage("iptables-persistent"), sudo("/etc/init.d/iptables-persistent save"))); + public String saveIptablesRules() { + return bash.alternatives(bash.sudo("service iptables save"), + bash.chain(bash.installPackage("iptables-persistent"), bash.sudo("/etc/init.d/iptables-persistent save"))); } /** @@ -139,8 +140,8 @@ public class IptablesCommands { * * @return Returns the command that cleans up iptables rules. */ - public static String cleanUpIptablesRules() { - return sudo("/sbin/iptables -F"); + public String cleanUpIptablesRules() { + return bash.sudo("/sbin/iptables -F"); } /** @@ -148,8 +149,8 @@ public class IptablesCommands { * * @return Returns the command that list all the iptables rules. */ - public static String listIptablesRule() { - return sudo("/sbin/iptables -L -v -n"); + public String listIptablesRule() { + return bash.sudo("/sbin/iptables -L -v -n"); } /** @@ -158,7 +159,7 @@ public class IptablesCommands { * @return Returns the command that inserts a rule on top of the iptables' * rules. */ - public static String insertIptablesRule(Chain chain, org.apache.brooklyn.util.net.Protocol protocol, int port, Policy policy) { + public String insertIptablesRule(Chain chain, org.apache.brooklyn.util.net.Protocol protocol, int port, Policy policy) { return addIptablesRule("-I", chain, Optional.<String> absent(), protocol, port, policy); } @@ -168,7 +169,7 @@ public class IptablesCommands { * @return Returns the command that inserts a rule on top of the iptables' * rules. */ - public static String insertIptablesRule(Chain chain, String networkInterface, org.apache.brooklyn.util.net.Protocol protocol, int port, Policy policy) { + public String insertIptablesRule(Chain chain, String networkInterface, org.apache.brooklyn.util.net.Protocol protocol, int port, Policy policy) { return addIptablesRule("-I", chain, Optional.of(networkInterface), protocol, port, policy); } @@ -177,7 +178,7 @@ public class IptablesCommands { * * @return Returns the command that appends a rule to iptables. */ - public static String appendIptablesRule(Chain chain, org.apache.brooklyn.util.net.Protocol protocol, int port, Policy policy) { + public String appendIptablesRule(Chain chain, org.apache.brooklyn.util.net.Protocol protocol, int port, Policy policy) { return addIptablesRule("-A", chain, Optional.<String> absent(), protocol, port, policy); } @@ -186,7 +187,7 @@ public class IptablesCommands { * * @return Returns the command that appends a rule to iptables. */ - public static String appendIptablesRule(Chain chain, String networkInterface, org.apache.brooklyn.util.net.Protocol protocol, int port, Policy policy) { + public String appendIptablesRule(Chain chain, String networkInterface, org.apache.brooklyn.util.net.Protocol protocol, int port, Policy policy) { return addIptablesRule("-A", chain, Optional.of(networkInterface), protocol, port, policy); } @@ -195,14 +196,14 @@ public class IptablesCommands { * * @return Returns the command that creates a rule for iptables. */ - public static String addIptablesRule(String direction, Chain chain, Optional<String> networkInterface, org.apache.brooklyn.util.net.Protocol protocol, int port, Policy policy) { + public String addIptablesRule(String direction, Chain chain, Optional<String> networkInterface, org.apache.brooklyn.util.net.Protocol protocol, int port, Policy policy) { String addIptablesRule; if(networkInterface.isPresent()) { addIptablesRule = String.format("/sbin/iptables %s %s -i %s -p %s --dport %d -j %s", direction, chain, networkInterface.get(), protocol, port, policy); } else { addIptablesRule = String.format("/sbin/iptables %s %s -p %s --dport %d -j %s", direction, chain, protocol, port, policy); } - return sudo(addIptablesRule); + return bash.sudo(addIptablesRule); } /** @@ -210,7 +211,7 @@ public class IptablesCommands { * * @return Returns the command that adds firewalld direct rule. */ - public static String addFirewalldRule(Chain chain, org.apache.brooklyn.util.net.Protocol protocol, int port, Policy policy) { + public String addFirewalldRule(Chain chain, org.apache.brooklyn.util.net.Protocol protocol, int port, Policy policy) { return addFirewalldRule(chain, Optional.<String>absent(), protocol, port, policy); } @@ -219,7 +220,7 @@ public class IptablesCommands { * * @return Returns the command that adds firewalld direct rule. */ - public static String addFirewalldRule(Chain chain, Optional<String> networkInterface, org.apache.brooklyn.util.net.Protocol protocol, int port, Policy policy) { + public String addFirewalldRule(Chain chain, Optional<String> networkInterface, org.apache.brooklyn.util.net.Protocol protocol, int port, Policy policy) { String command = new String("/usr/bin/firewall-cmd"); String commandPermanent = new String("/usr/bin/firewall-cmd --permanent"); @@ -228,6 +229,6 @@ public class IptablesCommands { String commandParameters = String.format(" --direct --add-rule ipv4 filter %s 0 %s -p %s --dport %d -j %s", chain, interfaceParameter, protocol, port, policy); - return sudo(chain(command + commandParameters, commandPermanent + commandParameters)); + return bash.sudo(bash.chain(command + commandParameters, commandPermanent + commandParameters)); } }
