summaryrefslogtreecommitdiffstats
path: root/node-admin
diff options
context:
space:
mode:
authorJon Marius Venstad <jvenstad@yahoo-inc.com>2018-03-12 15:58:48 +0100
committerJon Marius Venstad <jvenstad@yahoo-inc.com>2018-03-12 15:58:58 +0100
commit96d471be29e995b02a46ff51ec7c691ea6bab383 (patch)
tree9ac16d3d1477339cb30843bd2a853892ea6ea97b /node-admin
parent6b1f2ba9ad2fca1e13b72efd134f42c4eebbc0c7 (diff)
Rework Template(File) to allow String input
Diffstat (limited to 'node-admin')
-rw-r--r--node-admin/src/main/application/templates/motd.sh.vm27
-rw-r--r--node-admin/src/main/application/templates/prompt.sh.vm27
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/containerdata/MotdContainerData.java47
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/containerdata/PromptContainerData.java41
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/file/Template.java55
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/file/TemplateFile.java47
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/containerdata/MotdContainerDataTest.java6
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/containerdata/PromptContainerDataTest.java2
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/nodeagent/NodeAgentImplTest.java6
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/file/TemplateTest.java (renamed from node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/file/TemplateFileTest.java)28
10 files changed, 146 insertions, 140 deletions
diff --git a/node-admin/src/main/application/templates/motd.sh.vm b/node-admin/src/main/application/templates/motd.sh.vm
deleted file mode 100644
index 43087520368..00000000000
--- a/node-admin/src/main/application/templates/motd.sh.vm
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/usr/bin/env bash
-
-function motd {
-
- local -r uptime=$(uptime | cut -f 3- -d ' ')
-
- local -r no_color='\e[0m'
- local -r green='\e[0;32m'
-## Use red zone name for main prod zones, yellow for other main zones and no colour for cd and dev zones.
- local -r alert=#if($zone.getSystem() == "main")#if($zone.getEnvironment() == "prod")'\e[0;91m'#else'\e[0;33m'#end#else$green#end
-
-
- echo -e "
-${green}Zone : ${alert}$zone.getSystem().toUpperCase() $zone.getEnvironment().toUpperCase() $zone.getRegion().toUpperCase()
-${green}Node type : ${no_color}$node.nodeType
-${green}Host name : ${no_color}$(hostname)
-${green}Uptime : ${no_color}$uptime
-${green}Version : ${no_color}wanted=$node.wantedVespaVersion.orElse("unknown") installed=$node.vespaVersion.orElse("unknown")
-#if($node.owner.isPresent())
-${green}Node state : ${no_color}$node.nodeState
-${green}Owner : ${no_color}$node.owner.get().tenant $node.owner.get().application $node.owner.get().instance
-#end
-"
-}
-
-# Display motd (gently)
-[ ! -f ~/.hushlogin ] && motd
diff --git a/node-admin/src/main/application/templates/prompt.sh.vm b/node-admin/src/main/application/templates/prompt.sh.vm
deleted file mode 100644
index 73232907a32..00000000000
--- a/node-admin/src/main/application/templates/prompt.sh.vm
+++ /dev/null
@@ -1,27 +0,0 @@
-# Make sure we get UTC/GMT all over
-export TZ=UTC
-
-# Skip the rest for non-interactice shells
-[ -z "$PS1" ] && return
-
-# Check the window size after each command and, if necessary,
-# Update the values of LINES and COLUMNS.
-shopt -s checkwinsize
-
-# Colors; see https://wiki.archlinux.org/index.php/Color_Bash_Prompt
-color_off='\[\e[0m\]' # Text Reset
-color_bold='\[\e[1m\]' # Bold text
-
-env_colour=#if($zone.getSystem() == "main")#if($zone.getEnvironment() == "prod")'\e[0;91m'#else'\e[0;33m'#end#else$green#end
-
-
-PS1="${env_colour}$zone.getRegion().toUpperCase()${color_off} [\u@${color_bold}\h${color_off}:\w]\$ "
-
-# Fix colors
-if type dircolors > /dev/null 2>&1; then
- eval $(dircolors -b)
-fi
-
-# Make PS1 available in sub-shells
-export PS1
-
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/containerdata/MotdContainerData.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/containerdata/MotdContainerData.java
index 566e8ca5c39..9c6a9adf1f1 100644
--- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/containerdata/MotdContainerData.java
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/containerdata/MotdContainerData.java
@@ -3,7 +3,7 @@ package com.yahoo.vespa.hosted.node.admin.containerdata;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.vespa.hosted.node.admin.ContainerNodeSpec;
import com.yahoo.vespa.hosted.node.admin.component.Environment;
-import com.yahoo.vespa.hosted.node.admin.task.util.file.TemplateFile;
+import com.yahoo.vespa.hosted.node.admin.task.util.file.Template;
import com.yahoo.vespa.hosted.provision.Node.State;
import java.nio.file.Path;
@@ -11,21 +11,51 @@ import java.nio.file.Paths;
import java.util.Optional;
import java.util.function.BiConsumer;
+/**
+ * @author jvenstad
+ */
public class MotdContainerData {
private static final Path motdPath = Paths.get("etc/profile.d/motd.sh");
- private static final Path templatePath = Paths.get("src/main/application/templates/motd.sh.vm");
+ private static final String templateString = "#!/usr/bin/env bash\n" +
+ "\n" +
+ "function motd {\n" +
+ "\n" +
+ " local -r uptime=$(uptime | cut -f 3- -d ' ')\n" +
+ "\n" +
+ " local -r no_color='\\e[0m'\n" +
+ " local -r green='\\e[0;32m'\n" +
+ "## Use red zone name for main prod zones, yellow for other main zones and no colour for cd and dev zones.\n" +
+ " local -r alert=#if($zone.getSystem() == \"main\")#if($zone.getEnvironment() == \"prod\")'\\e[0;91m'#else'\\e[0;33m'#end#else$green#end\n" +
+ "\n" +
+ "\n" +
+ " echo -e \"\n" +
+ "${green}Zone : ${alert}$zone.getSystem().toUpperCase() $zone.getEnvironment().toUpperCase() $zone.getRegion().toUpperCase()\n" +
+ "${green}Node type : ${no_color}$node.type()\n" +
+ "${green}Host name : ${no_color}$(hostname)\n" +
+ "${green}Uptime : ${no_color}$uptime\n" +
+ "${green}Version : ${no_color}wanted = $node.wanted().orElse(\"unknown\"); installed = $node.installed().orElse(\"unknown\")\n" +
+ "#if($node.owner().isPresent())\n" +
+ "${green}Node state : ${no_color}$node.state()\n" +
+ "${green}Owner : ${no_color}$node.owner().get().serializedForm()\n" +
+ "#end\n" +
+ "\"\n" +
+ "}\n" +
+ "\n" +
+ "# Display motd (gently)\n" +
+ "[ ! -f ~/.hushlogin ] && motd\n";
- private final TemplateFile template;
+ private final String renderedString;
public MotdContainerData(ContainerNodeSpec nodeSpec, Environment environment) {
- template = new TemplateFile(templatePath)
+ renderedString = Template.of(templateString)
.set("zone", environment)
.set("node", new Node(nodeSpec.nodeType,
nodeSpec.nodeState,
nodeSpec.vespaVersion,
nodeSpec.wantedVespaVersion,
- nodeSpec.owner));
+ nodeSpec.owner))
+ .render();
}
public void writeTo(ContainerData containerData) {
@@ -33,11 +63,12 @@ public class MotdContainerData {
}
void writeTo(BiConsumer<Path, String> fileWriter) {
- System.out.println(template.render());
- fileWriter.accept(motdPath, template.render());
+ fileWriter.accept(motdPath, renderedString);
}
- private static class Node {
+
+ // Needs to be public for Velocity to use it.
+ public static class Node {
private final String type;
private final State state;
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/containerdata/PromptContainerData.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/containerdata/PromptContainerData.java
index 18fd12c0a47..ea9b2312b77 100644
--- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/containerdata/PromptContainerData.java
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/containerdata/PromptContainerData.java
@@ -1,7 +1,7 @@
package com.yahoo.vespa.hosted.node.admin.containerdata;
import com.yahoo.vespa.hosted.node.admin.component.Environment;
-import com.yahoo.vespa.hosted.node.admin.task.util.file.TemplateFile;
+import com.yahoo.vespa.hosted.node.admin.task.util.file.Template;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -10,13 +10,40 @@ import java.util.function.BiConsumer;
public class PromptContainerData {
private static final Path promptPath = Paths.get("etc/profile.d/prompt.sh");
- private static final Path templatePath = Paths.get("src/main/application/templates/prompt.sh.vm");
-
- private final TemplateFile template;
+ private static final String templateString = "# Make sure we get UTC/GMT all over\n" +
+ "export TZ=UTC\n" +
+ "\n" +
+ "# Skip the rest for non-interactice shells\n" +
+ "[ -z \"$PS1\" ] && return\n" +
+ "\n" +
+ "# Check the window size after each command and, if necessary,\n" +
+ "# Update the values of LINES and COLUMNS.\n" +
+ "shopt -s checkwinsize\n" +
+ "\n" +
+ "# Colors; see https://wiki.archlinux.org/index.php/Color_Bash_Prompt\n" +
+ "color_off='\\[\\e[0m\\]' # Text Reset\n" +
+ "color_bold='\\[\\e[1m\\]' # Bold text\n" +
+ "\n" +
+ "env_colour=#if($zone.getSystem() == \"main\")#if($zone.getEnvironment() == \"prod\")'\\e[0;91m'#else'\\e[0;33m'#end#else$green#end\n" +
+ "\n" +
+ "\n" +
+ "PS1=\"${env_colour}$zone.getRegion().toUpperCase()${color_off} [\\u@${color_bold}\\h${color_off}:\\w]\\$ \"\n" +
+ "\n" +
+ "# Fix colors\n" +
+ "if type dircolors > /dev/null 2>&1; then\n" +
+ " eval $(dircolors -b)\n" +
+ "fi\n" +
+ "\n" +
+ "# Make PS1 available in sub-shells\n" +
+ "export PS1\n" +
+ "\n";
+
+ private final String renderedString;
public PromptContainerData(Environment environment) {
- template = new TemplateFile(templatePath)
- .set("zone", environment);
+ renderedString = Template.of(templateString)
+ .set("zone", environment)
+ .render();
}
public void writeTo(ContainerData containerData) {
@@ -24,7 +51,7 @@ public class PromptContainerData {
}
void writeTo(BiConsumer<Path, String> fileWriter) {
- fileWriter.accept(promptPath, template.render());
+ fileWriter.accept(promptPath, renderedString);
}
}
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/file/Template.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/file/Template.java
new file mode 100644
index 00000000000..6092cc1f038
--- /dev/null
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/file/Template.java
@@ -0,0 +1,55 @@
+// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.hosted.node.admin.task.util.file;
+
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.Velocity;
+import org.apache.velocity.app.VelocityEngine;
+
+import java.io.StringWriter;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+/**
+ * Uses the Velocity engine to render a template, to and from both String and Path objects.
+ *
+ * @author hakonhall
+ * @author jvenstad
+ */
+public class Template {
+
+ private final VelocityEngine velocityEngine = new VelocityEngine();
+ private final VelocityContext velocityContext = new VelocityContext();
+ private final String template;
+
+ private Template(String template) {
+ this.template = template;
+
+ velocityEngine.addProperty(Velocity.RUNTIME_LOG_LOGSYSTEM_CLASS,
+ "org.apache.velocity.runtime.log.NullLogSystem");
+ velocityEngine.init();
+ }
+
+ public static Template at(Path templatePath) {
+ return of(IOExceptionUtil.uncheck(() -> new String(Files.readAllBytes(templatePath))));
+ }
+
+ public static Template of(String template) {
+ return new Template(template);
+ }
+
+ public Template set(String name, Object value) {
+ velocityContext.put(name, value);
+ return this;
+ }
+
+ public FileWriter getFileWriterTo(Path destinationPath) {
+ return new FileWriter(destinationPath, this::render);
+ }
+
+ public String render() {
+ StringWriter writer = new StringWriter();
+ velocityEngine.evaluate(velocityContext, writer, "Template", template);
+ return writer.toString();
+ }
+
+}
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/file/TemplateFile.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/file/TemplateFile.java
deleted file mode 100644
index ecde0aca9af..00000000000
--- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/file/TemplateFile.java
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.hosted.node.admin.task.util.file;
-
-import org.apache.velocity.Template;
-import org.apache.velocity.VelocityContext;
-import org.apache.velocity.app.Velocity;
-import org.apache.velocity.app.VelocityEngine;
-
-import java.io.StringWriter;
-import java.nio.file.Path;
-
-/**
- * Make a file based on a Velocity template file.
- *
- * @author hakonhall
- */
-public class TemplateFile {
- private final Path templatePath;
- private final VelocityEngine velocityEngine;
- private final VelocityContext velocityContext = new VelocityContext();
-
- public TemplateFile(Path templatePath) {
- this.templatePath = templatePath;
- velocityEngine = new VelocityEngine();
- velocityEngine.addProperty(
- Velocity.RUNTIME_LOG_LOGSYSTEM_CLASS,
- "org.apache.velocity.runtime.log.NullLogSystem");
- velocityEngine.addProperty(Velocity.FILE_RESOURCE_LOADER_PATH, templatePath.getParent().toString());
- velocityEngine.init();
- }
-
- public TemplateFile set(String name, Object value) {
- velocityContext.put(name, value);
- return this;
- }
-
- public FileWriter getFileWriterTo(Path destinationPath) {
- return new FileWriter(destinationPath, this::render);
- }
-
- public String render() {
- Template template = velocityEngine.getTemplate(templatePath.getFileName().toString(), "UTF-8");
- StringWriter writer = new StringWriter();
- template.merge(velocityContext, writer);
- return writer.toString();
- }
-}
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/containerdata/MotdContainerDataTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/containerdata/MotdContainerDataTest.java
index 9d2ef7980c5..5554f99299e 100644
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/containerdata/MotdContainerDataTest.java
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/containerdata/MotdContainerDataTest.java
@@ -46,10 +46,10 @@ public class MotdContainerDataTest {
assertTrue(content.contains("tenant"));
assertTrue(content.contains("[0;91m"));
assertTrue(content.contains("MAIN PROD AWS-US-EAST-1A"));
- assertTrue(content.contains("tenant1 application1 default"));
+ assertTrue(content.contains("tenant1:application1:default"));
assertTrue(content.contains("dirty"));
- assertTrue(content.contains("wanted-unknown"));
- assertTrue(content.contains("installed=7.0.0"));
+ assertTrue(content.contains("wanted = unknown"));
+ assertTrue(content.contains("installed = 7.0.0"));
});
}
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/containerdata/PromptContainerDataTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/containerdata/PromptContainerDataTest.java
index 4d64af75453..7a1ba860ad1 100644
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/containerdata/PromptContainerDataTest.java
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/containerdata/PromptContainerDataTest.java
@@ -1,9 +1,7 @@
package com.yahoo.vespa.hosted.node.admin.containerdata;
-import com.yahoo.vespa.hosted.node.admin.ContainerNodeSpec;
import com.yahoo.vespa.hosted.node.admin.component.Environment;
import com.yahoo.vespa.hosted.node.admin.config.ConfigServerConfig;
-import com.yahoo.vespa.hosted.provision.Node;
import org.junit.Test;
import java.nio.file.Paths;
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/nodeagent/NodeAgentImplTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/nodeagent/NodeAgentImplTest.java
index a97a11faab8..9d379babeca 100644
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/nodeagent/NodeAgentImplTest.java
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/nodeagent/NodeAgentImplTest.java
@@ -175,6 +175,7 @@ public class NodeAgentImplTest {
when(nodeRepository.getContainerNodeSpec(hostName)).thenReturn(Optional.of(nodeSpec));
when(pathResolver.getApplicationStoragePathForNodeAdmin()).thenReturn(Files.createTempDirectory("foo"));
+ when(pathResolver.getApplicationStoragePathForHost()).thenReturn(Files.createTempDirectory("bar"));
when(dockerOperations.pullImageAsyncIfNeeded(eq(dockerImage))).thenReturn(false);
when(storageMaintainer.getDiskUsageFor(eq(containerName))).thenReturn(Optional.of(201326592000L));
@@ -230,7 +231,7 @@ public class NodeAgentImplTest {
}
@Test
- public void containerIsRestartedIfFlavorChanged() {
+ public void containerIsRestartedIfFlavorChanged() throws IOException {
final long wantedRestartGeneration = 1;
final long currentRestartGeneration = 1;
ContainerNodeSpec.Builder specBuilder = nodeSpecBuilder
@@ -253,6 +254,7 @@ public class NodeAgentImplTest {
.thenReturn(Optional.of(thirdSpec));
when(dockerOperations.pullImageAsyncIfNeeded(any())).thenReturn(true);
when(storageMaintainer.getDiskUsageFor(eq(containerName))).thenReturn(Optional.of(201326592000L));
+ when(pathResolver.getApplicationStoragePathForHost()).thenReturn(Files.createTempDirectory("bar"));
nodeAgent.converge();
nodeAgent.converge();
@@ -472,6 +474,7 @@ public class NodeAgentImplTest {
when(nodeRepository.getContainerNodeSpec(eq(hostName))).thenReturn(Optional.of(nodeSpec));
when(pathResolver.getApplicationStoragePathForNodeAdmin()).thenReturn(Files.createTempDirectory("foo"));
+ when(pathResolver.getApplicationStoragePathForHost()).thenReturn(Files.createTempDirectory("bar"));
when(storageMaintainer.getDiskUsageFor(eq(containerName))).thenReturn(Optional.of(201326592000L));
nodeAgent.tick();
@@ -583,6 +586,7 @@ public class NodeAgentImplTest {
when(dockerOperations.getContainerStats(eq(containerName)))
.thenReturn(Optional.of(stats1))
.thenReturn(Optional.of(stats2));
+ when(pathResolver.getApplicationStoragePathForHost()).thenReturn(Files.createTempDirectory("bar"));
nodeAgent.converge(); // Run the converge loop once to initialize lastNodeSpec
nodeAgent.updateContainerNodeMetrics(); // Update metrics once to init and lastCpuMetric
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/file/TemplateFileTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/file/TemplateTest.java
index b1d88fdaaee..7aa672e9e80 100644
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/file/TemplateFileTest.java
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/file/TemplateTest.java
@@ -2,40 +2,31 @@
package com.yahoo.vespa.hosted.node.admin.task.util.file;
+import com.google.common.jimfs.Jimfs;
import com.yahoo.vespa.hosted.node.admin.component.TaskContext;
-import org.junit.Rule;
+import com.yahoo.vespa.test.file.TestFileSystem;
import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
import java.io.IOException;
+import java.nio.file.FileSystem;
import java.nio.file.Path;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
-/**
- * WARNING: Velocity does not honor an alternative FileSystem like JimFS.
- */
-public class TemplateFileTest {
- @Rule
- public TemporaryFolder folder = new TemporaryFolder();
-
- private void writeFile(Path path, String content) {
- UnixPath unixPath = new UnixPath(path);
- unixPath.createParents();
- unixPath.writeUtf8File(content);
- }
+public class TemplateTest {
@Test
public void basic() throws IOException {
+ FileSystem fileSystem = TestFileSystem.create();
+ Path templatePath = fileSystem.getPath("/example.vm");
String templateContent = "a $x, $y b";
- Path templatePath = folder.newFile("example.vm").toPath();
- writeFile(templatePath, templateContent);
+ new UnixPath(templatePath).writeUtf8File(templateContent);
- Path toPath = folder.newFile().toPath();
+ Path toPath = fileSystem.getPath("/example");
TaskContext taskContext = mock(TaskContext.class);
- boolean converged = new TemplateFile(templatePath)
+ boolean converged = Template.at(templatePath)
.set("x", "foo")
.set("y", "bar")
.getFileWriterTo(toPath)
@@ -46,4 +37,5 @@ public class TemplateFileTest {
String actualContent = new UnixPath(toPath).readUtf8File();
assertEquals("a foo, bar b", actualContent);
}
+
} \ No newline at end of file