diff --git a/CHANGELOG.md b/CHANGELOG.md index 983caadce28..c231d733288 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ * Fix #6008: removing the optional dependency on bouncy castle #### Dependency Upgrade +* Fix #6052: Removed dependency on no longer maintained com.github.mifmif:generex #### New Features diff --git a/openshift-client/pom.xml b/openshift-client/pom.xml index 2d65f01c89f..66f25352e29 100644 --- a/openshift-client/pom.xml +++ b/openshift-client/pom.xml @@ -62,12 +62,6 @@ openshift-client-api - - com.github.mifmif - generex - ${generex.version} - - io.sundr @@ -126,6 +120,11 @@ junit-jupiter-engine test + + org.junit.jupiter + junit-jupiter-params + test + org.mockito diff --git a/openshift-client/src/main/java/io/fabric8/openshift/client/dsl/internal/core/CharRange.java b/openshift-client/src/main/java/io/fabric8/openshift/client/dsl/internal/core/CharRange.java new file mode 100644 index 00000000000..a0224b8a6fc --- /dev/null +++ b/openshift-client/src/main/java/io/fabric8/openshift/client/dsl/internal/core/CharRange.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2015 Red Hat, Inc. + * + * Licensed 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 io.fabric8.openshift.client.dsl.internal.core; + +final class CharRange { + private final char start; + private final char end; + + public CharRange(char start, char end) { + this.start = start; + this.end = end; + } + + public char start() { + return start; + } + + public char end() { + return end; + } + + public String rangeStr() { + return new String(new char[] { start, end }); + } + +} diff --git a/openshift-client/src/main/java/io/fabric8/openshift/client/dsl/internal/core/ExpressionValueGenerator.java b/openshift-client/src/main/java/io/fabric8/openshift/client/dsl/internal/core/ExpressionValueGenerator.java new file mode 100644 index 00000000000..711b5ae69b4 --- /dev/null +++ b/openshift-client/src/main/java/io/fabric8/openshift/client/dsl/internal/core/ExpressionValueGenerator.java @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2015 Red Hat, Inc. + * + * Licensed 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 io.fabric8.openshift.client.dsl.internal.core; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +// from: https://github.com/openshift/library-go/blob/aed018c215a122871be1768155cf9f3e658278fc/pkg/template/generator/expressionvalue.go +public class ExpressionValueGenerator { + private static final String ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + private static final String NUMERALS = "0123456789"; + private static final String SYMBOLS = "~!@#$%^&*()-_+={}[]\\|<,>.?/\"';:`"; + private static final String ASCII = ALPHABET + NUMERALS + SYMBOLS; + + private static final Pattern RANGE_EXP = Pattern.compile("([\\\\]?[a-zA-Z0-9]\\-?[a-zA-Z0-9]?)"); + private static final Pattern GENERATORS_EXP = Pattern.compile("\\[([a-zA-Z0-9\\-\\\\]+)\\](\\{([0-9]+)\\})"); + private static final Pattern EXPRESSION_EXP = Pattern.compile("\\[(\\\\w|\\\\d|\\\\a|\\\\A)|([a-zA-Z0-9]\\-[a-zA-Z0-9])+\\]"); + + private final Random random; + + public ExpressionValueGenerator(Random random) { + this.random = random; + } + + public String generateValue(final String expression) { + String result = expression; + Matcher matcher = GENERATORS_EXP.matcher(result); + while (matcher.find()) { + String matched = result.substring(matcher.start(), matcher.end()); + String ranges = getRange(matched); + int length = Integer.parseInt(getLength(matched)); + + result = replaceWithGenerated( + result, + matched, + findExpressionPos(ranges), + length, + random); + matcher = GENERATORS_EXP.matcher(result); + } + return result; + } + + private static String alphabetSlice(char from, char to) { + int leftPos = ASCII.indexOf(from); + int rightPos = ASCII.lastIndexOf(to) + 1; + if (leftPos > rightPos) { + throw new IllegalArgumentException("invalid range specified: " + from + "-" + to); + } + return ASCII.substring(leftPos, rightPos); + } + + private static String replaceWithGenerated(String s, String expression, List ranges, int length, Random random) { + StringBuilder alphabet = new StringBuilder(); + for (CharRange r : ranges) { + switch (r.rangeStr()) { + case "\\w": + alphabet.append(ALPHABET).append(NUMERALS).append("_"); + break; + case "\\d": + alphabet.append(NUMERALS); + break; + case "\\a": + alphabet.append(ALPHABET).append(NUMERALS); + break; + case "\\A": + alphabet.append(SYMBOLS); + break; + default: + alphabet.append(alphabetSlice(r.start(), r.end())); + break; + } + } + String alphabetStr = removeDuplicateChars(alphabet.toString()); + StringBuilder result = new StringBuilder(length); + for (int i = 0; i < length; i++) { + result.append(alphabetStr.charAt(random.nextInt(alphabetStr.length()))); + } + return s.replace(expression, result.toString()); + } + + protected static String removeDuplicateChars(String input) { + return input.chars() + .distinct() + .mapToObj(c -> String.valueOf((char) c)) + .collect(Collectors.joining()); + } + + private static List findExpressionPos(String s) { + Matcher matcher = RANGE_EXP.matcher(s); + List result = new ArrayList<>(); + while (matcher.find()) { + result.add(new CharRange(s.charAt(matcher.start()), s.charAt(matcher.end() - 1))); + } + return result; + } + + private static String getRange(String s) { + int lastOpenCurly = s.lastIndexOf("{"); + String expr = s.substring(0, lastOpenCurly); + if (!EXPRESSION_EXP.matcher(expr).find()) { + throw new IllegalArgumentException("malformed expression syntax: " + expr); + } + return expr; + } + + private static String getLength(String s) { + int lastOpenCurly = s.lastIndexOf("{"); + String lengthStr = s.substring(lastOpenCurly + 1, s.length() - 1); + int length = Integer.parseInt(lengthStr); + if (length > 0 && length <= 255) { + return lengthStr; + } + throw new IllegalArgumentException("invalid range: must be within [1-255] characters (" + length + ")"); + } + +} diff --git a/openshift-client/src/main/java/io/fabric8/openshift/client/dsl/internal/core/TemplateOperationsImpl.java b/openshift-client/src/main/java/io/fabric8/openshift/client/dsl/internal/core/TemplateOperationsImpl.java index dcb1111b476..cc215dac61b 100644 --- a/openshift-client/src/main/java/io/fabric8/openshift/client/dsl/internal/core/TemplateOperationsImpl.java +++ b/openshift-client/src/main/java/io/fabric8/openshift/client/dsl/internal/core/TemplateOperationsImpl.java @@ -16,7 +16,6 @@ package io.fabric8.openshift.client.dsl.internal.core; import com.fasterxml.jackson.core.type.TypeReference; -import com.mifmif.common.regex.Generex; import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.api.model.KubernetesList; import io.fabric8.kubernetes.api.model.KubernetesListBuilder; @@ -50,6 +49,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.concurrent.ThreadLocalRandom; import static io.fabric8.openshift.client.OpenShiftAPIGroups.TEMPLATE; @@ -185,8 +185,8 @@ public KubernetesList processLocally(Map valuesMap) { } else if (Utils.isNotNullOrEmpty(parameter.getValue())) { parameterValue = parameter.getValue(); } else if (EXPRESSION.equals(parameter.getGenerate())) { - Generex generex = new Generex(parameter.getFrom()); - parameterValue = generex.random(); + ExpressionValueGenerator valueGenerator = new ExpressionValueGenerator(ThreadLocalRandom.current()); + parameterValue = valueGenerator.generateValue(parameter.getFrom()); } else if (parameter.getRequired() == null || !parameter.getRequired()) { parameterValue = ""; } else { diff --git a/openshift-client/src/test/java/io/fabric8/openshift/client/dsl/internal/core/ExpressionValueGeneratorTest.java b/openshift-client/src/test/java/io/fabric8/openshift/client/dsl/internal/core/ExpressionValueGeneratorTest.java new file mode 100644 index 00000000000..c1b53e1019d --- /dev/null +++ b/openshift-client/src/test/java/io/fabric8/openshift/client/dsl/internal/core/ExpressionValueGeneratorTest.java @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2015 Red Hat, Inc. + * + * Licensed 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 io.fabric8.openshift.client.dsl.internal.core; + +import org.junit.Test; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.ArgumentsProvider; +import org.junit.jupiter.params.provider.ArgumentsSource; + +import java.util.Random; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +// from: https://github.com/openshift/library-go/blob/aed018c215a122871be1768155cf9f3e658278fc/pkg/template/generator/expressionvalue_test.go +public class ExpressionValueGeneratorTest { + + static class ExpressionValuesArgumentsProvider implements ArgumentsProvider { + @Override + public Stream provideArguments(ExtensionContext extensionContext) throws Exception { + return Stream.of( + Arguments.of("test[0-9]{1}x", "test6x"), + Arguments.of("[0-1]{8}", "11100011"), + Arguments.of("0x[A-F0-9]{4}", "0x545A"), + Arguments.of("[a-zA-Z0-9]{8}", "KaP00gmR"), + Arguments.of("test[A-Z0-9]{4}template", "testQU7Etemplate"), + Arguments.of("[\\d]{3}", "645"), + Arguments.of("[\\w]{20}", "0V86t3tosHvHdzUwQKTB"), + Arguments.of("[\\a]{10}", "KaP00gmRS2"), + Arguments.of("[\\A]{10}", ">|>~-{'>,]"), + Arguments.of("strongPassword[\\w]{3}[\\A]{3}", "strongPassword0V8~-{"), + Arguments.of("admin[0-9]{2}[A-Z]{2}", "admin64DK"), + Arguments.of("admin[0-9]{2}test[A-Z]{2}", "admin64testDK")); + } + } + + @ParameterizedTest + @ArgumentsSource(ExpressionValuesArgumentsProvider.class) + public void generateStringFromRegEx(String input, String expected) { + // Arrange + Random random = new Random(); + random.setSeed(7); + ExpressionValueGenerator generator = new ExpressionValueGenerator(random); + + // Act + String result = generator.generateValue(input); + + // Assert + assertEquals(expected, result); + } + + static class DuplicatesArgumentsProvider implements ArgumentsProvider { + @Override + public Stream provideArguments(ExtensionContext extensionContext) throws Exception { + return Stream.of( + Arguments.of("abcdefgh", "abcdefgh"), + Arguments.of("abcabc", "abc"), + Arguments.of("1111111", "1"), + Arguments.of("1234567890", "1234567890"), + Arguments.of("test@@", "tes@")); + } + } + + @ParameterizedTest + @ArgumentsSource(DuplicatesArgumentsProvider.class) + public void removeDuplicatedCharacters(String input, String expected) { + // Arrange + ExpressionValueGenerator generator = new ExpressionValueGenerator(new Random()); + + // Act + String result = ExpressionValueGenerator.removeDuplicateChars(input); + + // Assert + assertEquals(expected, result); + } + + @Test + public void maformedSyntax() { + // Arrange + ExpressionValueGenerator generator = new ExpressionValueGenerator(new Random()); + + // Act + IllegalArgumentException result = assertThrows(IllegalArgumentException.class, + () -> generator.generateValue("[ABC]{3}")); + + // Assert + assertTrue(result.getMessage().contains("malformed")); + assertTrue(result.getMessage().contains("syntax")); + } + + @Test + public void invalidRange() { + // Arrange + ExpressionValueGenerator generator = new ExpressionValueGenerator(new Random()); + + // Act + IllegalArgumentException result = assertThrows(IllegalArgumentException.class, + () -> generator.generateValue("[Z-A]{3}")); + + // Assert + assertTrue(result.getMessage().contains("invalid")); + assertTrue(result.getMessage().contains("range")); + } + + @Test + public void rangeOutOfBound() { + // Arrange + ExpressionValueGenerator generator = new ExpressionValueGenerator(new Random()); + + // Act + IllegalArgumentException result = assertThrows(IllegalArgumentException.class, + () -> generator.generateValue("[A-Z]{300}")); + + // Assert + assertTrue(result.getMessage().contains("invalid")); + assertTrue(result.getMessage().contains("range")); + } + + @Test + public void zeroRange() { + // Arrange + ExpressionValueGenerator generator = new ExpressionValueGenerator(new Random()); + + // Act + IllegalArgumentException result = assertThrows(IllegalArgumentException.class, + () -> generator.generateValue("[A-Z]{0}")); + + // Assert + assertTrue(result.getMessage().contains("invalid")); + assertTrue(result.getMessage().contains("range")); + } +} diff --git a/platforms/karaf/features/src/main/resources/feature.xml b/platforms/karaf/features/src/main/resources/feature.xml index 3dc44dbcf94..f53b7c076ef 100644 --- a/platforms/karaf/features/src/main/resources/feature.xml +++ b/platforms/karaf/features/src/main/resources/feature.xml @@ -26,7 +26,6 @@ mvn:com.fasterxml.jackson.datatype/jackson-datatype-jsr310/${jackson.bundle.version} mvn:org.yaml/snakeyaml/${snakeyaml.bundle.version} mvn:org.snakeyaml/snakeyaml-engine/${snakeyaml.version} - mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.generex/${generex.bundle.version} mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.automaton/${automaton.bundle.version} mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.conscrypt-openjdk/${conscrypt-openjdk-uber.bundle.version} mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.okhttp/${okhttp.bundle.version} diff --git a/pom.xml b/pom.xml index 148ebadaad4..82c78ab7b71 100644 --- a/pom.xml +++ b/pom.xml @@ -118,8 +118,6 @@ 2.4-M4-groovy-4.0 1.4.2_1 - 1.0.2 - 1.0.1_1 1.11-8_1 1.3.0 8.0.1 diff --git a/uberjar/pom.xml b/uberjar/pom.xml index 6e776049051..b4c17d32449 100644 --- a/uberjar/pom.xml +++ b/uberjar/pom.xml @@ -238,12 +238,6 @@ ${zjsonpatch.version} - - com.github.mifmif - generex - ${generex.version} - - org.junit.jupiter junit-jupiter-engine