Skip to content

Commit

Permalink
Merge pull request #1238 from jcarranzan/escape-chars-on-Win
Browse files Browse the repository at this point in the history
Fix QuarkusCliConfigEncryptIT for Windows OS
  • Loading branch information
michalvavrik authored Aug 25, 2024
2 parents 1acc0c4 + 9556b40 commit 6bd4c13
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

import io.smallrye.common.os.OS;

public class QuarkusConfigCommandResult {

final String applicationPropertiesAsString;
Expand All @@ -19,10 +21,24 @@ public QuarkusConfigCommandResult assertCommandOutputNotContains(String expected
}

public QuarkusConfigCommandResult assertCommandOutputContains(String expected) {
assertTrue(output.contains(expected.trim()), "Expected output '" + output + "' does not contain '" + expected + "'");
if (OS.WINDOWS.isCurrent()) {
String windowsEscapedExpected = normalizeString(expected);
String windowsEscapedOutput = normalizeString(output);

assertTrue(windowsEscapedOutput.contains(windowsEscapedExpected),
"Expected output '" + windowsEscapedExpected + "'does not contain '" + windowsEscapedOutput + "'");
} else {
assertTrue(output.contains(expected.trim()),
"Expected output '" + output + "' does not contain '" + expected + "'");
}
return this;
}

private String normalizeString(String str) {
String noAnsi = str.replaceAll("\\x1B\\[[;\\d]*m", "");
return noAnsi.replaceAll("\"", "").replaceAll("\n", " ").trim();
}

public QuarkusConfigCommandResult assertApplicationPropertiesContains(String str) {
assertTrue(applicationPropertiesAsString.contains(str),
"Expected value '" + str + "' is missing in application.properties: " + applicationPropertiesAsString);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@
import org.junit.jupiter.api.Assertions;

import io.quarkus.test.logging.Log;
import io.quarkus.test.util.QuarkusCLIUtils;
import io.quarkus.test.utils.Command;
import io.quarkus.test.utils.FileUtils;
import io.smallrye.common.os.OS;

public class QuarkusEncryptConfigCommandBuilder {

Expand All @@ -31,7 +33,12 @@ public class QuarkusEncryptConfigCommandBuilder {
}

public QuarkusEncryptConfigCommandBuilder secret(String secret) {
this.secret = secret;
if (OS.WINDOWS.isCurrent()) {
this.secret = QuarkusCLIUtils.escapeSecretCharsForWindows(secret);
} else {
this.secret = secret;
}

return this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import java.util.Objects;
import java.util.function.Consumer;

import io.quarkus.test.util.QuarkusCLIUtils;

public class QuarkusEncryptConfigCommandResult extends QuarkusConfigCommandResult {

private static final String SECRET_ENCRYPTED_TO = "was encrypted to";
Expand All @@ -19,7 +21,11 @@ public class QuarkusEncryptConfigCommandResult extends QuarkusConfigCommandResul

public String getGeneratedEncryptionKey() {
if (output.contains(WITH_GENERATED_KEY)) {
return output.transform(o -> o.substring(o.lastIndexOf(" "))).trim();
return output
.transform(o -> o.substring(o.lastIndexOf(" ")))
.transform(QuarkusCLIUtils::toUtf8)
.transform(QuarkusCLIUtils::removeAnsiAndHiddenChars)
.trim();
}
return null;
}
Expand All @@ -29,6 +35,8 @@ public String getEncryptedSecret() {
encryptedSecret = output
.transform(o -> o.split(SECRET_ENCRYPTED_TO)[1])
.transform(remaining -> remaining.split(WITH_GENERATED_KEY)[0])
.transform(QuarkusCLIUtils::toUtf8)
.transform(QuarkusCLIUtils::removeAnsiAndHiddenChars)
.trim();
}
return encryptedSecret;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

import java.util.ArrayList;

import io.quarkus.test.util.QuarkusCLIUtils;
import io.smallrye.common.os.OS;

public class QuarkusSetConfigCommandBuilder {

private final boolean updateScenario;
Expand All @@ -23,7 +26,11 @@ public QuarkusSetConfigCommandBuilder name(String name) {
}

public QuarkusSetConfigCommandBuilder value(String value) {
this.propertyValue = value;
if (OS.WINDOWS.isCurrent()) {
this.propertyValue = QuarkusCLIUtils.escapeSecretCharsForWindows(value);
} else {
this.propertyValue = value;
}
return this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
Expand All @@ -27,12 +29,15 @@
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;

import io.quarkus.test.bootstrap.QuarkusCliRestService;
import io.smallrye.common.os.OS;

public abstract class QuarkusCLIUtils {
public static final String RESOURCES_DIR = Paths.get("src", "main", "resources").toString();
public static final String PROPERTIES_FILE = "application.properties";
public static final String PROPERTIES_YAML_FILE = "application.yml";
public static final String POM_FILE = "pom.xml";
private static final String ANSI_BOLD_TEXT_ESCAPE_SEQ = "[1m";
private static final char ESCAPE_CHARACTER = 27;

/**
* This constant stands for number of fields in groupId:artifactId:version string, when separated via ":".
Expand Down Expand Up @@ -375,4 +380,45 @@ public String toString() {
return "Plugin {groupId=" + getGroupId() + ", artifactId=" + getArtifactId() + ", version=" + getVersion() + "}";
}
}

/**
* Escapes a command-line secret chars for Windows OS.
*/
public static String escapeSecretCharsForWindows(String secret) {
return "\"" + secret
.replace("\"", "\\\"")
+ "\"";
}

/**
* When Quarkus CLI prints out text, especially by {@code quarkus config encrypt} command,
* important parts (like encoded secrets) can be highlighted or there can be hidden chars.
* We recognize hidden chars etc. This method handles both situation. It's definitely imperfect,
* but we only deal with scenarios (issues) we run on.
*/
public static String removeAnsiAndHiddenChars(String text) {
if (OS.current() == OS.WINDOWS) {
var result = text
.trim()
.transform(t -> {
if (t.contains(ANSI_BOLD_TEXT_ESCAPE_SEQ)) {
return t.substring(ANSI_BOLD_TEXT_ESCAPE_SEQ.length());
}
return t;
})
.transform(t -> {
int idx = t.indexOf(ESCAPE_CHARACTER);
if (idx >= 0) {
return t.substring(0, idx);
}
return t;
});
return result;
}
return text;
}

public static String toUtf8(String t) {
return new String(t.getBytes(Charset.defaultCharset()), StandardCharsets.UTF_8);
}
}

0 comments on commit 6bd4c13

Please sign in to comment.