New scriptbuilder feature: CreateOrOverwriteFile

During the process got rid of the (to me) confusing addSpaceToEnsureWe... method
This commit is contained in:
Karel Vervaeke 2011-09-30 16:00:23 +02:00
parent 28a5c15ca0
commit 22ed06b641
12 changed files with 268 additions and 30 deletions

View File

@ -26,7 +26,6 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Pattern;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
@ -90,7 +89,7 @@ public class AppendFile implements Statement {
return new StatementList(statements).render(family);
}
private void hereFile(String path, StringBuilder builder) {
protected void hereFile(String path, StringBuilder builder) {
builder.append("cat >> ").append(path).append(" <<'").append(marker).append("'\n");
for (String line : lines) {
builder.append(line).append("\n");
@ -98,21 +97,14 @@ public class AppendFile implements Statement {
builder.append(marker).append("\n");
}
private Statement appendToFile(String line, String path, OsFamily family) {
protected Statement appendToFile(String line, String path, OsFamily family) {
String quote = "";
if (!ShellToken.VQ.to(family).equals("")) {
quote = "'";
} else {
line = escapeVarTokens(line, family);
}
return interpret(addSpaceToEnsureWeDontAccidentallyRedirectFd(String.format("echo %s%s%s>>%s{lf}", quote, line,
quote, path)));
}
public static final Pattern REDIRECT_FD_PATTERN = Pattern.compile(".*[0-2]>>.*");
static String addSpaceToEnsureWeDontAccidentallyRedirectFd(String line) {
return REDIRECT_FD_PATTERN.matcher(line).matches() ? line.replace(">>", " >>") : line;
return interpret(String.format("echo %s%s%s >>%s{lf}", quote, line, quote, path));
}
}

View File

@ -0,0 +1,118 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.scriptbuilder.domain;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static org.jclouds.scriptbuilder.domain.Statements.interpret;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Pattern;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
/**
* Creates a run script
*
* @author Adrian Cole
*/
public class CreateFile implements Statement {
public static final String MARKER = "END_OF_FILE";
final String path;
final Iterable<String> lines;
final String marker;
public CreateFile(String path, Iterable<String> lines) {
this(path, lines, MARKER);
}
public CreateFile(String path, Iterable<String> lines, String marker) {
this.path = checkNotNull(path, "path");
this.lines = checkNotNull(lines, "lines");
this.marker = checkNotNull(marker, "marker");
checkState(Iterables.size(lines) > 0, "you must pass something to execute");
}
public static String escapeVarTokens(String toEscape, OsFamily family) {
Map<String, String> inputToEscape = Maps.newHashMap();
for (ShellToken token : ImmutableList.of(ShellToken.VARL, ShellToken.VARR)) {
if (!token.to(family).equals("")) {
String tokenS = "{" + token.toString().toLowerCase() + "}";
inputToEscape.put(tokenS, "{escvar}" + tokenS);
}
}
for (Entry<String, String> entry : inputToEscape.entrySet()) {
toEscape = toEscape.replace(entry.getKey(), entry.getValue());
}
return toEscape;
}
@Override
public Iterable<String> functionDependencies(OsFamily family) {
return Collections.emptyList();
}
@Override
public String render(OsFamily family) {
List<Statement> statements = Lists.newArrayList();
if (family == OsFamily.UNIX) {
StringBuilder builder = new StringBuilder();
hereFile(path, builder);
statements.add(interpret(builder.toString()));
} else {
for (String line : lines) {
statements.add(appendToFile(line, path, family));
}
}
return new StatementList(statements).render(family);
}
private void hereFile(String path, StringBuilder builder) {
builder.append("cat > ").append(path).append(" <<'").append(marker).append("'\n");
for (String line : lines) {
builder.append(line).append("\n");
}
builder.append(marker).append("\n");
}
private Statement appendToFile(String line, String path, OsFamily family) {
String quote = "";
if (!ShellToken.VQ.to(family).equals("")) {
quote = "'";
} else {
line = escapeVarTokens(line, family);
}
return interpret(addSpaceToEnsureWeDontAccidentallyRedirectFd(String.format("echo %s%s%s>>%s{lf}", quote, line,
quote, path)));
}
public static final Pattern REDIRECT_FD_PATTERN = Pattern.compile(".*[0-2]>>.*");
static String addSpaceToEnsureWeDontAccidentallyRedirectFd(String line) {
return REDIRECT_FD_PATTERN.matcher(line).matches() ? line.replace(">>", " >>") : line;
}
}

View File

@ -0,0 +1,67 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.scriptbuilder.domain;
import static org.jclouds.scriptbuilder.domain.Statements.interpret;
import java.util.List;
import com.google.common.collect.Lists;
/**
* Creates a run script
*
* @author Adrian Cole
*/
public class CreateOrOverwriteFile extends AppendFile {
public CreateOrOverwriteFile(String path, Iterable<String> lines) {
super(path, lines);
}
public CreateOrOverwriteFile(String path, Iterable<String> lines, String marker) {
super(path, lines, marker);
}
@Override
public String render(OsFamily family) {
List<Statement> statements = Lists.newArrayList();
if (family == OsFamily.UNIX) {
StringBuilder builder = new StringBuilder();
hereFile(path, builder);
statements.add(interpret(builder.toString()));
} else {
// Windows:
statements.add(interpret(String.format("copy /y CON %s{lf}", path))); // This clears the file
for (String line : lines) {
statements.add(appendToFile(line, path, family));
}
}
return new StatementList(statements).render(family);
}
protected void hereFile(String path, StringBuilder builder) {
builder.append("cat > ").append(path).append(" <<'").append(marker).append("'\n");
for (String line : lines) {
builder.append(line).append("\n");
}
builder.append(marker).append("\n");
}
}

View File

@ -71,6 +71,14 @@ public class Statements {
return new AppendFile(path, lines, marker);
}
public static Statement createOrOverwriteFile(String path, Iterable<String> lines) {
return new CreateOrOverwriteFile(path, lines);
}
public static Statement createOrOverwriteFile(String path, Iterable<String> lines, String marker) {
return new CreateOrOverwriteFile(path, lines, marker);
}
public static CreateRunScript createRunScript(String instanceName, Iterable<String> exports, String pwd,
Iterable<Statement> statements) {// TODO: convert so
// that

View File

@ -40,19 +40,12 @@ public class AppendFileTest {
public void testUNIX() throws IOException {
assertEquals(statement.render(OsFamily.UNIX), CharStreams.toString(Resources.newReaderSupplier(Resources
.getResource("client_rb." + ShellToken.SH.to(OsFamily.UNIX)), Charsets.UTF_8)));
.getResource("client_rb_append." + ShellToken.SH.to(OsFamily.UNIX)), Charsets.UTF_8)));
}
public void testWINDOWS() throws IOException {
assertEquals(statement.render(OsFamily.WINDOWS), CharStreams.toString(Resources.newReaderSupplier(Resources
.getResource("client_rb." + ShellToken.SH.to(OsFamily.WINDOWS)), Charsets.UTF_8)));
}
public void testRedirectGuard() {
assertEquals(AppendFile.addSpaceToEnsureWeDontAccidentallyRedirectFd("foo>>"), "foo>>");
assertEquals(AppendFile.addSpaceToEnsureWeDontAccidentallyRedirectFd("foo0>>"), "foo0 >>");
assertEquals(AppendFile.addSpaceToEnsureWeDontAccidentallyRedirectFd("foo1>>"), "foo1 >>");
assertEquals(AppendFile.addSpaceToEnsureWeDontAccidentallyRedirectFd("foo2>>"), "foo2 >>");
.getResource("client_rb_append." + ShellToken.SH.to(OsFamily.WINDOWS)), Charsets.UTF_8)));
}
}

View File

@ -0,0 +1,51 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.scriptbuilder.domain;
import static org.jclouds.scriptbuilder.domain.Statements.createOrOverwriteFile;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import org.testng.annotations.Test;
import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableList;
import com.google.common.io.CharStreams;
import com.google.common.io.Resources;
/**
* @author Karel Vervaeke
*/
@Test(groups = "unit")
public class CreateOrOverwriteFileTest {
Statement statement = createOrOverwriteFile("{root}etc{fs}chef{fs}client.rb", ImmutableList.of("log_level :info",
"log_location STDOUT", String.format("chef_server_url \"%s\"", "http://localhost:4000")));
public void testUNIX() throws IOException {
assertEquals(statement.render(OsFamily.UNIX), CharStreams.toString(Resources.newReaderSupplier(Resources
.getResource("client_rb_overwrite." + ShellToken.SH.to(OsFamily.UNIX)), Charsets.UTF_8)));
}
public void testWINDOWS() throws IOException {
assertEquals(statement.render(OsFamily.WINDOWS), CharStreams.toString(Resources.newReaderSupplier(Resources
.getResource("client_rb_overwrite." + ShellToken.SH.to(OsFamily.WINDOWS)), Charsets.UTF_8)));
}
}

View File

@ -1,3 +0,0 @@
echo log_level :info>>c:\etc\chef\client.rb
echo log_location STDOUT>>c:\etc\chef\client.rb
echo chef_server_url "http://localhost:4000">>c:\etc\chef\client.rb

View File

@ -0,0 +1,3 @@
echo log_level :info >>c:\etc\chef\client.rb
echo log_location STDOUT >>c:\etc\chef\client.rb
echo chef_server_url "http://localhost:4000" >>c:\etc\chef\client.rb

View File

@ -0,0 +1,4 @@
copy /y CON c:\etc\chef\client.rb
echo log_level :info >>c:\etc\chef\client.rb
echo log_location STDOUT >>c:\etc\chef\client.rb
echo chef_server_url "http://localhost:4000" >>c:\etc\chef\client.rb

View File

@ -0,0 +1,5 @@
cat > /etc/chef/client.rb <<'END_OF_FILE'
log_level :info
log_location STDOUT
chef_server_url "http://localhost:4000"
END_OF_FILE

View File

@ -28,7 +28,7 @@ goto CASE_%1
echo stop %RUNTIME%
GOTO END_SWITCH
:CASE_status
echo hello world>>%TEMP%\%USERNAME%\scripttest\temp.txt
echo hello world >>%TEMP%\%USERNAME%\scripttest\temp.txt
echo the following should be []: [%RUNTIME%]
GOTO END_SWITCH
:END_SWITCH