summaryrefslogtreecommitdiffstats
path: root/node-admin/src/main
diff options
context:
space:
mode:
authorHåkon Hallingstad <hakon@oath.com>2018-11-23 17:30:13 +0100
committerHåkon Hallingstad <hakon@oath.com>2018-11-23 17:30:13 +0100
commitcadcac9a8c0501f86372eb05d107d7b089643d0a (patch)
tree9593cc78763cba8e790e49c21f28a19182002765 /node-admin/src/main
parentf67aa7bfa1553d8cc19ce4eef96f42ff8c31a320 (diff)
Add flags module
FileFlagSource reads flags from files in /etc/vespa/flags and is a component that can be injected in host admin, config server, etc. A flag named foo corresponds to filename foo. In general a FlagSource manages: - Feature flags: A feature is either set (true/enabled) or otherwise false. Touching a file foo means the feature flag foo is set (true). - Value flags: Either a String or empty if not set. The String corresponds to the file content. The plan is to make the config server another source of flags. A unified FlagSource can merge the two sources with some priority and used in e.g. parts of node-admin. In other parts one would only have access to the file source. Defines various flag facades: - FeatureFlag: Used to test whether a feature has been enabled or not. - IntFlag - JacksonFlag: Deserializes JSON to Jackson class, or return default if unset. - LongFlag - OptionalJacksonFlag: Deserializes JSON to Jackson class, or empty if unset. - OptionalStringFlag - StringFlag This is part of removing some of the last Chef recipes. Some minor tweaks have been necessary as part of this and are included in this PR (test whether a systemd service exists, task-friendly file deletion, allow capitalized letters in YUM package name).
Diffstat (limited to 'node-admin/src/main')
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/file/FileDeleter.java33
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/file/UnixPath.java19
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/process/CommandLine.java9
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/systemd/SystemCtl.java17
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/yum/YumPackageName.java2
5 files changed, 69 insertions, 11 deletions
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/file/FileDeleter.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/file/FileDeleter.java
new file mode 100644
index 00000000000..efb56be56c5
--- /dev/null
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/file/FileDeleter.java
@@ -0,0 +1,33 @@
+package com.yahoo.vespa.hosted.node.admin.task.util.file;
+
+import com.yahoo.vespa.hosted.node.admin.component.TaskContext;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.logging.Logger;
+
+import static com.yahoo.yolean.Exceptions.uncheck;
+
+/**
+ * Deletes a file or empty directory.
+ *
+ * @author hakonhall
+ */
+public class FileDeleter {
+ private static final Logger logger = Logger.getLogger(FileDeleter.class.getName());
+
+ private final Path path;
+
+ public FileDeleter(Path path) {
+ this.path = path;
+ }
+
+ public boolean converge(TaskContext context) {
+ boolean deleted = uncheck(() -> Files.deleteIfExists(path));
+ if (deleted) {
+ context.recordSystemModification(logger, "Deleted file or directory " + path);
+ }
+
+ return deleted;
+ }
+}
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/file/UnixPath.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/file/UnixPath.java
index 4bd3aad3f52..1b927cfc682 100644
--- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/file/UnixPath.java
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/file/UnixPath.java
@@ -49,16 +49,6 @@ public class UnixPath {
return path;
}
- public boolean createParents() {
- Path parent = path.getParent();
- if (Files.isDirectory(parent)) {
- return false;
- }
-
- uncheck(() -> Files.createDirectories(parent));
- return true;
- }
-
public String readUtf8File() {
return new String(readBytes(), StandardCharsets.UTF_8);
}
@@ -141,6 +131,15 @@ public class UnixPath {
return this;
}
+ public UnixPath createParents() {
+ Path parent = path.getParent();
+ if (!Files.isDirectory(parent)) {
+ uncheck(() -> Files.createDirectories(parent));
+ }
+
+ return this;
+ }
+
public UnixPath createDirectory(String permissions) {
Set<PosixFilePermission> set = getPosixFilePermissionsFromString(permissions);
FileAttribute<Set<PosixFilePermission>> attribute = PosixFilePermissions.asFileAttribute(set);
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/process/CommandLine.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/process/CommandLine.java
index 44b7da9367b..940b3255766 100644
--- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/process/CommandLine.java
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/process/CommandLine.java
@@ -180,6 +180,15 @@ public class CommandLine {
}
/**
+ * By default, a non-zero exit code causes the command execution to fail. This method
+ * will override that predicate.
+ */
+ public CommandLine setSuccessfulExitCodePredicate(Predicate<Integer> successPredicate) {
+ successfulExitCodePredicate = successPredicate;
+ return this;
+ }
+
+ /**
* By default, the output of the command is parsed as UTF-8. This method will set a
* different encoding.
*/
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/systemd/SystemCtl.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/systemd/SystemCtl.java
index b61ebb610af..77510f7b6ef 100644
--- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/systemd/SystemCtl.java
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/systemd/SystemCtl.java
@@ -20,6 +20,9 @@ public class SystemCtl {
// Valid systemd property names from looking at a couple of services.
private static final Pattern PROPERTY_NAME_PATTERN = Pattern.compile("^[a-zA-Z]+$");
+ // Last line of `systemctl list-unit-files <unit>` prints '0 unit files listed.'
+ private static final Pattern UNIT_FILES_LISTED_PATTERN = Pattern.compile("([0-9]+) unit files listed\\.");
+
// Patterns matching properties output by the 'systemctl show' command.
private static final Pattern UNIT_FILE_STATE_PROPERTY_PATTERN = createPropertyPattern("UnitFileState");
private static final Pattern ACTIVE_STATE_PROPERTY_PATTERN = createPropertyPattern("ActiveState");
@@ -53,6 +56,20 @@ public class SystemCtl {
public SystemCtlStop stop(String unit) { return new SystemCtlStop(unit); }
public SystemCtlRestart restart(String unit) { return new SystemCtlRestart(unit); }
+ public boolean serviceExists(TaskContext context, String unit) {
+ return terminal.newCommandLine(context)
+ .add("systemctl").add("list-unit-files").add(unit + ".service").executeSilently()
+ .mapOutput(output -> {
+ // Last line of the form: "1 unit files listed."
+ Matcher matcher = UNIT_FILES_LISTED_PATTERN.matcher(output);
+ if (!matcher.find()) {
+ throw new IllegalArgumentException();
+ }
+
+ return !matcher.group(1).equals("0");
+ });
+ }
+
public class SystemCtlEnable extends SystemCtlCommand {
private SystemCtlEnable(String unit) {
super("enable", unit);
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/yum/YumPackageName.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/yum/YumPackageName.java
index a3a154e2175..fb85815c70f 100644
--- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/yum/YumPackageName.java
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/yum/YumPackageName.java
@@ -43,7 +43,7 @@ public class YumPackageName {
private static final Pattern NAME_VER_REL_PATTERN = Pattern.compile("^((.+)-)?" +
"([a-z0-9._]*[0-9][a-z0-9._]*)-" + // ver contains at least one digit
"([a-z0-9._]*[0-9][a-z0-9._]*)$"); // rel contains at least one digit
- private static final Pattern NAME_PATTERN = Pattern.compile("^[a-z0-9._-]+$");
+ private static final Pattern NAME_PATTERN = Pattern.compile("^[a-zA-Z0-9._-]+$");
private final Optional<String> epoch;
private final String name;